c# – 有一个简单的方法来创建一个不可变的版本的类吗?

有没有一个简单的方法来使一个实例不可变?

我们举一个例子,我有一个类持有大量数据字段(仅数据,没有行为):

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.

那么有什么自动的方式来产生这个不可变的类?或者另一种允许在创建过程中发生变异的方式,一旦初始化就可以变得不可

我知道这些字段可以被标记为“只读”,但该对象将被初始化在类之外,并将所有字段作为构造函数传递,似乎是一个坏主意(参数太多).

最佳答案
不,没有什么简单的方法可以使任何类型不可变,特别是如果你想要“深度”不变性(即通过不可变对象无法达到可变对象的话).您将不得不明确地将您的类型设计为不可变的.使类型不可变的通常机制是:

>声明(属性支持)字段只读. (或者,从C#6 / Visual Studio 2015开始,使用read-only auto-implemented properties.)
>不要暴露属性设置器,只允许访客.
>为了初始化(属性支持)字段,必须在构造函数中初始化它们.因此,将(property)值传递给构造函数.
>不要暴露可变对象,例如基于可变的默认类型(如T [],List< T>,Dictionary< TKey,TValue等)的集合. 如果需要公开集合,请将其返回到防止修改的包装器中(例如.AsReadOnly()),或者至少返回内部集合的新副本.
>使用Builder模式.以下示例对于执行模式正义来说太小了,因为通常建议在需要创建非平凡对象图的情况下进行;然而,基本的想法是这样的:

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# – 有一个简单的方法来创建一个不可变的版本的类吗? - 代码日志