在c#中,值类型是可变的还是不可变的?
本文关键字:不可变 类型 | 更新日期: 2023-09-27 18:05:43
值类型的行为表明,无论我们保存的是什么值,都不能通过其他变量来改变。
但是我仍然对我在这篇文章的标题中提到的内容感到困惑。有人能解释一下吗?
值类型可以是可变的或者(对一些奇怪的边缘情况取模)不可变的,这取决于你如何编写它们。
可变:public struct MutableValueType
{
public int MyInt { get; set; }
}
不变:
public struct ImmutableValueType
{
private readonly int myInt;
public ImmutableValueType(int i) { this.myInt = i; }
public int MyInt { get { return this.myInt; } }
}
内置值类型(int
, double
等)是不可变的,但是您可以很容易地创建自己的可变struct
。
SomeType t = new SomeType();
t.X = 5;
SomeType u = t;
t.X = 10;
Console.WriteLine(u.X);
这取决于。如果SomeType
是一个值类型,它打印5
,这是一个相当令人困惑的结果。
所有基本值类型,如int, double,float都是不可变的。但是结构本身是可变的。所以你必须采取措施使它们不可变,否则会造成很多混乱。
任何保存信息的值类型实例都可以被写入包含它的存储位置的代码修改,并且任何值类型实例都不能被写入包含它的存储位置的代码修改。这些特征使得可变值类型的私有存储位置在许多情况下都是理想的数据容器,因为它们结合了源于可变性的更新便利性和来自不可变性的控制。请注意,可以为值类型编写这样一种代码,即如果不首先拥有包含所需数据的实例(可能是新创建的临时实例),并使用后一个实例的内容覆盖前一个实例的内容,则不可能改变现有实例,但这不会使值类型的可变性比没有这种能力时更多或更少。在许多情况下,它只会使突变变得尴尬,使它看起来像这样的语句:
<>之前MyKeyValuePair =新的KeyValuePair<长,long> (MyKeyValuePair。键+ 1,MyKeyValuePair.Value + 1比;;之前将创建一个新实例,但不影响现有实例。如果KeyValuePair
是一个不可变类,并且一个线程正在执行MyKeyValuePair.ToString()
,而另一个线程正在执行上述代码,则ToString
调用将作用于旧实例或新实例,因此将产生旧值或新值。因为KeyValuePair
是一个结构体,所以上面的语句将创建一个新实例,但是它不会让MyKeyValuePair
引用这个新实例——它只是使用这个新实例作为模板,它的字段将被复制到MyKeyValuePair
。如果KeyValuePair
是一个可变结构体,那么上面代码最自然的表达可能是:
或者:
<>之前var temp = MyKeyValuePair;MyKeyValuePair。Key = temp.Key+1;MyKeyValuePair。Value = temp.Value+1;之前和线程含义会更清晰。