我如何创build一个不可变的类?

我正在创build一个不可变的类。
我已将所有属性标记为只读。

我有一个class级的项目清单。
虽然如果属性是只读的,那么列表可以被修改。

公开列表的IEnumerable使其不可变。
我想知道为了使一个类不可变而必须遵循的基本规则是什么?

我认为你在正确的轨道上 –

  • 注入到类中的所有信息都应该在构造函数中提供
  • 所有的属性应该只是获得者
  • 如果一个集合(或数组)被传入构造函数,它应该被复制以防止调用者稍后修改它
  • 如果要返回集合,请返回一个副本或只读版本(例如,使用ArrayList.ReadOnly或类似的方法) – 您可以将其与以前的点结合使用,并存储只读副本调用者访问它),返回一个枚举器,或使用一些其他的方法/属性,允许只读访问集合
  • 请记住,如果您的任何成员都是可变的,那么您仍然可能具有可变类的外观 – 如果是这种情况,您应该复制掉您希望保留的任何状态,并避免返回整个可变对象,除非您复制它们在将它们返回给调用者之前 – 另一个select是只返回可变对象的不可变“部分” – 感谢@Brian Rasmussen鼓励我扩展这一点

为了不变,所有的属性和字段都应该是只读的。 而任何列表中的项目本身都应该是不可变的。

您可以创build只读列表属性,如下所示:

public class MyClass { public MyClass(..., IList<MyType> items) { ... _myReadOnlyList = new List<MyType>(items).AsReadOnly(); } public IList<MyType> MyReadOnlyList { get { return _myReadOnlyList; } } private IList<MyType> _myReadOnlyList } 

另外请记住:

 public readonly object[] MyObjects; 

即使标有readonly关键字也不是不可变的。 您仍然可以通过索引访问器更改单个数组引用/值。

使用ReadOnlyCollection类。 它位于System.Collections.ObjectModel命名空间中。

在任何返回列表(或在构造函数中)的列表中,将列表设置为只读集合。

 using System.Collections.ObjectModel; ... public MyClass(..., List<ListItemType> theList, ...) { ... this.myListItemCollection= theList.AsReadOnly(); ... } public ReadOnlyCollection<ListItemType> ListItems { get { return this.myListItemCollection; } } 

另一种select是使用访问者模式,而不是公开任何内部集合。