如何实例化一个大的不可变类型?
我有一个包含大约 40 个属性(所有值类型)的类型,代表我的业务的一种交易类型。此类的一个实例对应于我的数据库中的一行。我想保持我的类不可变,因为它只用于读取操作,但我不确定如何在初始化期间设置 40 个属性。
通常,我对不可变类型使用构造函数初始化,但我想避免编写具有 40 个参数的构造函数。我的财产的设置者目前是私人的,尽管我愿意有足够的理由进行更改。是否有处理这种情况的通用方法或解决问题的更好方法?
I have a type with about 40 properties (all value types) that represents a type of transaction for my business. An instance of this class corresponds to a row in my database. I would like to keep my class immutable since it will only ever be used for read operations, but I am not sure how to go about setting 40 properties during initialization.
Typically I use constructor initialization for immutable types, but I would like to avoid writing a constructor with 40 parameters. The setters for my properties are currently private though I am willing to change with good enough reason. Is there a common way to handle this situation or a better way to approach the problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您的问题不在于具有 40 个参数的构造函数,而在于具有 40 个字段的类。
我建议打破这个。这些领域是否以某种方式相关?如果是这样,请将它们分组到一个公共对象(例如 EmailInfo)中,然后让您的大对象仅引用分组对象。
一旦您的类具有较少的直接属性,创建一个采用这些分组对象的构造函数就不那么可怕了。
Your problem isn't so much a constructor with 40 arguments, but a class with 40 fields.
I'd recommend breaking this down. Are any of the fields related in some way? If so, group them into a common object (e.g. EmailInfo), then have your big object just reference the grouping objects.
Once your class has fewer direct properties, creating a constructor that takes those grouping objects isn't so terrible.
快点。您提到对象上的设置器是私有的。如果是这种情况,那么您的对象不是不可变的(否则设置器不可能存在)。最好的情况是你的对象是只读的。
对于真正的不可变对象,别无选择,只能让构造函数接受初始化对象所需的所有值。减少构造函数中参数数量的最佳方法是将值分组为更大的对象,然后将其传递给构造函数。尽管我不会这样做,除非这些值在逻辑上是相关的。
如果您的不可变类型确实需要 40 个值,并且它们在其他方面不相关,则最好的方法是使用具有 40 个值的构造函数。那或进一步分解大的不可变对象。
Quick point. You mentioned your setters on the object are private. If that is the case then your object is not immutable (otherwise setters couldn't exist). At best your object is read only.
For a true immutable object there is no choice but to have the constructor take in all of the values necessary to initialize the object. The best way to reduce the number of parameters in the constructor is to group the values into bigger objects which are then passed to the constructor. Although I wouldn't do that unless the values are otherwise logically related.
If your immutable type does truly need the 40 values and they are otherwise unrelated, the best approach is to have a constructor with 40 values. That or further break down the big immutable object.
我喜欢使用可变对象来实例化不可变对象的方法;可变对象只是为了整齐地传递选项。 .NET 框架中的一个示例是 进程启动信息。
虽然我对“40 个属性”保持沉默,但我发现上述方法非常有效。一个额外的好处是
XInfo
,并且X
中使用的内部结构可以完全不同,只要您可以提供合理的映射即可。I like the approach of using a mutable object to instantiate an immutable object; the mutable object is just for tidy passing of options. One example of this in the .NET framework is ProcessStartInfo.
While I'll hold my tongue about the '40 properties', I find the above approach works pretty well. An added bonus is the
XInfo
and the internal structure used inX
can be entirely different, as long as you can provide a sane mapping.如果我按照你的话“但我不确定如何在初始化期间设置 40 个属性。”,看来你的问题是一个具有太多字段/属性的类。
使其不可变似乎不是问题,因为您已经知道如何做到这一点。
我建议(像其他人一样)重构和提取类。
If i go by your words "but I am not sure how to go about setting 40 properties during initialization.", it appears that your problem is a class with too many fields/properties.
Doesnt seem to be a problem of making it immutable, because you already know how to do that.
I would suggest (like others), Refactor and Extract Class.
作为替代方案,您可以使您的类派生自 freezable,我认为这可能是您正在寻找的解决方案。您可以实例化对象,设置值,然后将其设置为冻结。一旦将其设置为冻结,该类就变为“只读”。
As an alternative, you can make your class derive from freezable, I think this may be the solution you are searching for. You can Instatiate the object, set the values, then set it frozen. Once you set it frozen the class is 'read only'.
我建议将参数放入一个或多个结构中,并让对象保存这些结构。嵌套对象是可能的,但会比嵌套结构增加更多开销。
作为替代方案,您可以创建一个抽象基类,其中包含所有属性的“只读必须覆盖”版本。由此派生出可变和不可变的对象类。不可变对象可以在其构造函数中接受基类,并使用所有只读属性来构建新对象。可变类可以提供一种使用方法写入属性的方法、具有与只读版本不同名称的读写属性等。
I would suggest putting the parameters into one or more structures, and having the object hold those structures. Nesting objects would be possible, but would add more overhead than nesting structures.
As an alternative, you could create an abstract base class with "readonly mustoverride" versions of all your properties. From this, derive a mutable and immutable object class. The immutable one can accept the base class in its constructor, and use all the readonly properties to build the new object. The mutable class can provide a means of writing the properties using methods, read-write properties with different names from the readonly versions, etc.