有没有一种简单的方法可以使实例不可变?
举个例子,我有一个包含很多数据字段的类(只有数据,没有行为):
class MyObject
{
// lots of fields painful to initialize all at once
// so we make fields mutable :
public String Title { get; set; }
public String Author { get; set; }
// ...
}
创建示例:
MyObject CreationExample(String someParameters)
{
var obj = new MyObject
{
Title = "foo"
// lots of fields initialization
};
// even more fields initialization
obj.Author = "bar";
return obj;
}
但现在我已经完全创建了我的对象,我不希望对象再可变(因为数据消费者永远不需要更改状态),所以我想要类似的东西 List.AsReadOnly :
var immutableObj = obj.AsReadOnly();
但是如果我想要这种行为,我需要创建另一个具有完全相同的字段但没有 setter 的类。
那么有什么自动生成这个不可变类的方法吗?或者另一种在创建期间允许可变性但在初始化后不可变的方法?
我知道字段可以标记为“只读”,但对象将在类之外初始化,将所有字段作为构造函数参数传递似乎是个坏主意(参数太多)。
最佳答案
不,没有简单的方法可以使任何类型不可变,尤其是如果您想要“深度”不变性(即无法通过不可变对象(immutable对象)访问可变对象)。您将必须明确地将您的类型设计为不可变的。使类型不可变的常用机制是:
- 声明(属性支持)字段
readonly
. (或者,从 C# 6/Visual Studio 2015 开始,使用 read-only auto-implemented properties 。) 不要公开属性 setter,只公开 getter。
为了初始化(属性支持)字段,您必须在构造函数中初始化它们。因此,将(属性)值传递给构造函数。
不要公开可变对象,例如基于默认可变类型(如
T[]
、List<T>
、Dictionary<TKey,TValue>
等)的集合。如果您需要公开集合,请在防止修改的包装器中返回它们(例如
.AsReadOnly()
),或者至少返回内部集合的新副本。使用构建器模式。下面的例子太简单了,不能很好地解释模式,因为通常建议在需要创建非平凡对象图的情况下使用它;尽管如此,基本思想是这样的:
class FooBuilder // mutable version used to prepare immutable objects { public int X { get; set; } public List<string> Ys { get; set; } public Foo Build() { return new Foo(x, ys); } } class Foo // immutable version { public Foo(int x, List<string> ys) { this.x = x; this.ys = new List<string>(ys); // create a copy, don't use the original } // since that is beyond our control private readonly int x; private readonly List<string> ys; … }
关于c# - 有没有一种简单的方法来制作类的不可变版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26105608/