从这个答案,我知道 KeyValuePair 是不可变的。
我浏览了文档,但找不到任何关于不可变行为的信息。
我想知道如何确定类型是否不可变?
我认为没有标准的方法可以做到这一点,因为 C# 中没有官方的不变性概念。我能想到的唯一方法是查看某些事物,表明概率更高:
1) 该类型的所有属性都有一个私有的set
2)所有字段都是const
/readonly
或私有的
3)没有明显/已知副作用的方法
4)此外,作为一个结构通常是一个很好的指示(如果它是 BCL 类型或有人对此有指导)
类似的东西ImmutabeAttribute
会很好。这里有一些想法(评论中的某处),但我还没有在“现实生活”中看到一个。
AKeyValuePair<T1,T2>
是一个没有反射的结构,它只能通过复制另一个KeyValuePair<T1,T2>
包含所需值的内容在其构造函数之外进行变异。注意声明:
MyKeyValuePair = new KeyValuePair(1,2);
像对结构的所有类似构造函数调用一样,实际上通过创建一个新的临时实例KeyValuePair<int,int>
(在构造函数本身执行之前发生)、设置该实例的字段值(由构造函数完成)、复制该新临时的所有公共和私有字段来工作实例到MyKeyValuePair
,然后丢弃临时实例。
考虑以下代码:
静态 KeyValuePair MyKeyValuePair; // 某个类中的字段 // 线程 1 MyKeyValuePair = new KeyValuePair(1,1); // *** MyKeyValuePair = new KeyValuePair(2,2); //线程2 st = MyKeyValuePair.ToString();
因为MyKeyValuePair
长度正好是四个字节,所以 Thread1 中的第二条语句将同时更新两个字段。尽管如此,如果 Thread1 中的第二条语句在 Thread2 对 and 的评估之间执行,则第二条语句MyKeyValuePair.Key.ToString()
将MyKeyValuePair.Value.ToString()
作用ToString()
于结构的新变异值,即使第一个已经完成的语句对变异ToString()
之前的值进行了操作。
所有重要的结构,无论它们是如何声明的,都对其字段具有相同的不变性规则:可以更改结构的代码可以更改其字段;不能改变结构的代码不能改变它的字段。一些结构可能会迫使人们通过箍来更改其中一个字段,但是将结构类型设计为“不可变”既没有必要也不足以确保实例的不变性。“不可变”结构类型有一些合理的用途,但如果有任何事情需要比具有暴露公共字段的结构所必需的更多注意,那么这些用例需要更多注意。
第一个迹象是概述中的属性文档说“获取键/值对中的键”。第二个更明确的指示将在属性本身的描述中: