C# 如何创建一个不可变的类?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/352471/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 00:13:03  来源:igfitidea点击:

How do I create an immutable Class?

c#.netimmutability

提问by Biswanath

I am working on creating an immutable class.
I have marked all the properties as read-only.

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

I have a list of items in the class.
Although if the property is read-only the list can be modified.

我有一个班级物品清单。
尽管如果属性是只读的,则可以修改列表。

Exposing the IEnumerable of the list makes it immutable.
I wanted to know what is the basic rules one has to follow to make a class immutable ?

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

采纳答案by Blair Conrad

I think you're on the right track -

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

  • all information injected into the class should be supplied in the constructor
  • all properties should be getters only
  • if a collection (or Array) is passed into the constructor, it should be copied to keep the caller from modifying it later
  • if you're going to return your collection, either return a copy or a read-only version (for example, using ArrayList.ReadOnlyor similar - you can combine this with the previous point and storea read-only copy to be returned when callers access it), return an enumerator, or use some other method/property that allows read-only access into the collection
  • keep in mind that you still may have the appearance of a mutable class if any of your members are mutable - if this is the case, you should copy away whatever state you will want to retain and avoid returning entire mutable objects, unless you copy them before giving them back to the caller - another option is to return only immutable "sections" of the mutable object - thanks to @Brian Rasmussen for encouraging me to expand this point
  • 注入类的所有信息都应在构造函数中提供
  • 所有属性都应该只是吸气剂
  • 如果一个集合(或数组)被传递给构造函数,它应该被复制以防止调用者以后修改它
  • 如果您要返回您的集合,请返回副本或只读版本(例如,使用ArrayList.ReadOnly或类似的 - 您可以将其与前一点结合并存储只读副本,以便在调用者访问它),返回一个枚举器,或使用其他一些允许只读访问集合的方法/属性
  • 请记住,如果您的任何成员是可变的,您仍然可能具有可变类的外观 - 如果是这种情况,您应该复制掉您想要保留的任何状态并避免返回整个可变对象,除非您复制它们在将它们返回给调用者之前 - 另一种选择是仅返回可变对象的不可变“部分” - 感谢 @Brian Rasmussen 鼓励我扩展这一点

回答by Joe

To be immutable, all your properties and fields should be readonly. And the items in any list should themselves be immutable.

要保持不变,您的所有属性和字段都应该是只读的。并且任何列表中的项目本身应该是不可变的。

You can make a readonly list property as follows:

您可以按如下方式创建只读列表属性:

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

}

回答by lubos hasko

Also, keep in mind that:

另外,请记住:

public readonly object[] MyObjects;

is not immutable even if it's marked with readonly keyword. You can still change individual array references/values by index accessor.

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

回答by Andrew

Another option would be to use a visitor pattern instead of exposing any internal collections at all.

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

回答by mbillard

Use the ReadOnlyCollectionclass. It's situated in the System.Collections.ObjectModelnamespace.

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

On anything that returns your list (or in the constructor), set the list as a read-only collection.

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

using System.Collections.ObjectModel;

...

public MyClass(..., List<ListItemType> theList, ...)
{
    ...
    this.myListItemCollection= theList.AsReadOnly();
    ...
}

public ReadOnlyCollection<ListItemType> ListItems
{
     get { return this.myListItemCollection; }
}

回答by Imad

Using ReadOnlyCollectionwill restrict client from modifying it.

使用ReadOnlyCollection将限制客户端对其进行修改。