Mik*_*nch 8 .net c# immutability
对于可变类型,值和引用类型之间的行为差异很明显:
// Mutable value type
PointMutStruct pms1 = new PointMutStruct(1, 2);
PointMutStruct pms2 = pms1;
// pms1 == (1, 2); pms2 == (1, 2);
pms2.X = 3;
MutateState(pms1); // Changes the X property to 4.
// pms1 == (1, 2); pms2 == (3, 2);
// Mutable reference type
PointMutClass pmc1 = new PointMutClass(1, 2);
PointMutClass pmc2 = pmc1;
// pmc1 == (1, 2); pmc2 == (1, 2);
pmc2.X = 3;
MutateState(pmc1); // Changes the X property to 4.
// pmc1 == (4, 2); pmc2 == (4, 2);
Run Code Online (Sandbox Code Playgroud)
但是,对于不可变类型,这种差异不太明显:
// Immutable value type
PointImmStruct pis1 = new PointImmStruct(1, 2);
PointImmStruct pis2 = pis1;
// pis1 == (1, 2); pis2 == (1, 2);
pis2 = new PointImmStruct(3, pis2.Y);
// Can't mutate pis1
// pis1 == (1, 2); pis2 == (3, 2);
// Immutable reference type
PointImmClass pic1 = new PointImmClass(1, 2);
PointImmClass pic2 = pic1;
// pic1 == (1, 2); pic2 == (1, 2);
pic2 = new PointImmClass(3, pic2.Y);
// Can't mutate pic1 either
// pic1 == (1, 2); pic2 == (3, 2);
Run Code Online (Sandbox Code Playgroud)
不可变引用类型通常也使用值语义(例如规范示例System.String):
string s1 = GenerateTestString(); // Generate identical non-interned strings
string s2 = GenerateTestString(); // by dynamically creating them
// object.ReferenceEquals(strA, strB)) == false;
// strA.Equals(strB) == true
// strA == strB
Run Code Online (Sandbox Code Playgroud)
Eric Lippert之前在他的博客上讨论过(例如这里),在堆栈上分配的值类型经常(当这个讨论并不重要时)的事实是一个实现细节,它通常不会决定你是否制作对象是值或引用类型.
鉴于不可变类型行为的这种模糊区别,我们有什么标准来决定是否将不可变类型作为引用类型或值类型?
此外,由于不可变的强调值与变量,不可变类型是否总是实现值语义?
我会说Eric链接的博客文章给出了你的答案:
我很遗憾文件没有关注最相关的内容; 通过关注一个很大程度上不相关的实现细节,我们扩大了实现细节的重要性,并模糊了使值类型在语义上有用的重要性.我非常希望所有那些解释"堆栈"的文章都会花时间解释究竟"按价值复制"的含义,以及误解或误用"按值复制"会导致错误.
如果您的对象应具有"按值复制"语义,则将它们设为值类型.如果它们应具有"引用复制"语义,请将它们作为引用类型.
他也说这个,我同意:
我总是根据类型是在语义上表示值还是从语义上对某些东西的引用来选择值类型与引用类型.
| 归档时间: |
|
| 查看次数: |
1044 次 |
| 最近记录: |