我如何创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是使用访问者模式,而不是公开任何内部集合。