值类型的行为表明我们所持有的任何值都不能通过其他变量进行更改。
但是,我仍然对我在帖子标题中提到的内容感到困惑。有人可以澄清吗?
值类型的行为表明我们所持有的任何值都不能通过其他变量进行更改。
但是,我仍然对我在帖子标题中提到的内容感到困惑。有人可以澄清吗?
值类型可以是可变的或者(除了一些奇怪的边界情况)是不可变的,这取决于你如何编写它们。
可变的:
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都是不可变的。但结构体本身是可变的。因此,您必须采取措施使它们尽可能不可变,以避免造成许多混淆。
将创建一个新实例,但不会影响现有实例。如果KeyValuePair
是一个不可变类,并且一个线程正在执行MyKeyValuePair.ToString()
而另一个线程正在执行上述代码,则ToString
调用将作用于旧实例或新实例,并因此产生既有旧值也有新值的结果。然而,由于KeyValuePair
是一个结构体,上述语句将创建一个新实例,但它不会使MyKeyValuePair
引用新实例——它只会使用新实例作为模板,其字段将被复制到MyKeyValuePair
中。如果KeyValuePair
是一个可变结构体,则上述代码可能意图表达的最自然表达方式更像是:
MyKeyValuePair.Key += 1; MyKeyValuePair.Value += 1;
或者:
var temp = MyKeyValuePair; MyKeyValuePair.Key = temp.Key+1; MyKeyValuePair.Value = temp.Value+1;
这样,线程的影响将更加清晰。
u.X
并尝试弄清楚那可能是什么时,你可能会看到u
以X=5
初始化且从未修改过,并且可能会错误地得出u.X
也是5的结论。通过混合别名和突变,现在您需要玩(不可能的)跟随所有这些别名的游戏......如果“SomeType”在内部使用类似的技巧,祝你好运... - Eamon Nerbonne