什么是C#中的不可变类型和不可变属性?你能给出一个简单的例子吗?
不可变类型是指在初始化时其属性值可以被设置,一旦对象创建后,就不能再做任何更改。而不可变属性则是只读属性。
在下面的示例中,ImmutableType
是一个不可变类型,它有一个名为Test
的属性。这是一个只读属性,只能在构造函数中进行设置。
class ImmutableType
{
private readonly string _test;
public string Test
{
get { return _test; }
}
public ImmutableType(string test)
{
_test = test;
}
}
参见:维基百科文章,以及有关该主题的一些Stack Overflow问题和回答。
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
}
}
private set
仅提供了对同一类中属性更改的受限封装,因此并不是真正的不可变性:public string Test
{
get;
private set; // Not immutable, since this is still mutable from within the class
}
更多关于不可变性
正如其他人所说,不可变属性
是指一旦设置就无法更改的属性。在构造期间设置“唯一”值。
不可变类型
是指所有(外部可见)属性和字段都是不可变的类型 - 例如最初计划用于 C#7 的“Record”类型(希望现在是8) 将是一个不可变类型。其他不可变类型的示例包括 Tuples
和所有 匿名类。
C#中的不可变字段应使用 readonly
关键字进行限定 - 这由编译器强制执行,以确保没有其他代码尝试在构造函数之外更改该字段。
.Build()
步骤中获得最终的不可变对象。fretje是正确的。不可变类型的最流行的例子是C#中的string
对象。这就是StringBuilder
存在的全部原因。
C#中对于不可变性(immutability)没有明确的定义:
通常情况下,它要求所有公共字段为只读(readonly),并且所有公共属性具有init setter或无setter。
它也可以将此扩展到私有成员(尽管通常使用可变的私有成员来缓存值,例如哈希码)
它还可能意味着所有成员本身都是不可变类型。否则,消费者仍然可以通过调用成员方法来修改对象
它还可能意味着所有方法在使用相同参数调用时始终返回相同的输出。特别是一个不可变的GetHashCode()意味着该对象可以安全地用作字典等中的键
更强大且通常更有用的概念是“数据”(Data)——一种不可变类型,也具有值语义(通常通过从IEquatable<T>
继承实现)
以下是一个满足上述所有要求的“数据”类型示例:
record MyData(int age, DateTime JoinDate);
(请参见项目F,了解有关数据类型的更多信息)
{ get; }
来拥有不可变的自动实现属性。 - Scott Chamberlain