C#中的不可变类型和属性

时间:2010-03-29 11:56:55

标签: c# types immutability

C#中的不可变类型和不可变属性是什么意思?你能给出一个简单的例子吗?

4 个答案:

答案 0 :(得分:29)

不可变类型是一种只能在初始化时设置其属性的类型。创建对象后,就不能再进行任何更改。不可变属性只是一个只读属性。

在以下示例中,ImmutableType是一个具有一个属性Test的不可变类型。 Test是一个只读属性。它只能在施工时设置。

class ImmutableType
{
    private readonly string _test;
    public string Test
    {
        get { return _test; }
    }

    public ImmutableType(string test)
    {
        _test = test;
    }
}

另请参阅The Wikipedia articlesome Stack Overflow questions

答案 1 :(得分:4)

fretje是对的。不可变类型最流行的例子是C#中的string对象。这就是StringBuilder存在的全部原因。

答案 2 :(得分:4)

除了上面的@ fretje的回答,在C#6及更高版本中,getter-only auto properties现已实现,它允许不可变的自动属性,而无需额外的显式{{1}支持领域。等效代码将缩写为:

private readonly

请注意class ImmutableType { public string Test { get; // No Set at all, not even a private set. } public ImmutableType(string test) { Test = test; // The compiler understands this and initializes the backing field } } (最接近不变性可以在早期版本的C#中使用自动属性)只能在同一个类中提供对属性的更改的限制封装,因此不是真的不可改变的:

private set

有关不变性的更多信息

正如其他人所说,public string Test { get; private set; // Not immutable, since this is still mutable from within the class } 是一个设置后无法改变的属性。设置“唯一值”'通常在构造函数中完成。

immutable Property是一种所有(外部可见)属性和字段都是不可变的类型 - 例如"记录"最初为C#7 (hopefully now 8)安排的类型将是不可变类型。不可变类型的其他示例包括Tuples和所有anonymous classes

不可变字段应该使用C#中的immutable Type关键字进行限定 - 这是由编译器强制执行的,以确保没有其他代码尝试更改构造函数之外的字段。

在可能的情况下,字段,变量和属性的不变性被视为良好实践,因为这极大地减少了错误的表面积(因为字段表示对象的状态,防止对字段的更改减少了状态的数量)。

不可变性的好处在多线程程序中尤为重要,其中两个或多个线程同时访问同一个对象。由于多个并发读取线程可以安全地访问字段或属性的值,因此程序员不需要关心与其他线程更改字段相关的线程安全问题。

处理由多个组合对象组成的复杂对象时,不变性的一个常见缺点是需要一次性构建整个图形,这可能导致代码混乱。这里的一个常见解决方案是使用Builder pattern作为脚手架,它允许在步骤中构建瞬态的可变表示,然后在最后的readonly步骤中获得最终的不可变对象。 / p>

答案 3 :(得分:-1)

C# 中没有明确的不变性定义:

  • 通常要求所有公共字段都为只读,所有公共属性都需要有 init setter 或没有 setter。

  • 它还可以将其扩展到私有成员(尽管使用可变私有成员来缓存值(即哈希码)是很常见的)

  • 这也可能意味着所有成员本身都是不可变类型。否则消费者仍然可以通过调用成员方法来修改对象

  • 这也可能意味着所有方法在使用相同参数调用时总是返回相同的输出。特别是不可变的 GetHashCode() 意味着该对象可以安全地用作字典等中的键

一个更强大且通常更有用的概念是 - 'Data' 一种不可变类型,它也具有值语义(通常通过从 IEquatable<T> 继承)

以下是满足上述所有要求的“数据”类型示例:

record MyData(int age, DateTime JoinDate);

(有关数据类型如何有用的更多信息,请参阅项目 F