我正在创建一个不可变的类 我已将所有属性标记为只读。
我有班级中的项目清单 虽然如果属性是只读的,则可以修改列表。
公开列表的IEnumerable使其不可变 我想知道为了使一个类不可变而必须遵循的基本规则是什么?
答案 0 :(得分:113)
我认为你走在正确的轨道上 -
答案 1 :(得分:17)
要成为不可变的,所有属性和字段都应该是只读的。任何列表中的项目本身都应该是不可变的。
您可以按如下方式创建只读列表属性:
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
}
答案 2 :(得分:10)
另外,请记住:
public readonly object[] MyObjects;
即使用readonly关键字标记也不是不可变的。您仍然可以通过索引访问器更改单个数组引用/值。
答案 3 :(得分:4)
使用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; }
}
答案 4 :(得分:2)
您只需要L ... Ehm record
和 C#9.0 或更高版本。
public record Customer(string FirstName, string LastName, IEnumerable<string> Items);
//...
var person = new Customer("Test", "test", new List<string>() { "Test1", "Test2", "Test3" });
// you can't change anything within person variable
// person.FirstName = "NewName";
这被转换为具有三个属性FirstName
,LastName
和Items
的不变类,称为Customer。
如果您需要一个不可变(只读)集合作为类的属性,则最好将其公开为IEnumerable<T>
或ReadOnlyCollection<T>
,而不是System.Collections.Immutable
答案 5 :(得分:1)
另一种选择是使用访客模式而不是暴露任何内部集合。
答案 6 :(得分:0)
使用ReadOnlyCollection将限制客户端对其进行修改。
答案 7 :(得分:0)
最初的问答起始于2008年底,现在有一个 System.Collections.Immutable命名空间,我认为它可以追溯到最早的.NET Core(1.0)。在.NET Standard(当前版本2.1)和.NET Framework(当前版本4.8)中,命名空间仍然不可用。这个名称空间有很多不可变的集合,包括 ImmutableList ,这在原始问题中被问到。但是,我相信System.Collections.Immutable命名空间可能会出现在当前处于候选发布版本2的.NET 5中。
此外,从C#6开始,您只需使用 {get;就可以拥有不可变的自动实现属性。 } 。