【发布时间】:2011-08-23 17:42:12
【问题描述】:
对于可变类型,值类型和引用类型之间的行为差异很明显:
// 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);
但是,对于不可变类型,这种区别不太明确:
// 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);
不可变引用类型也经常使用值语义(例如规范示例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
Eric Lippert 之前在他的博客(例如here)上讨论过,值类型通常(什么时候对这个讨论并不重要)分配在堆栈上的事实是一个实现细节,它不应该通常决定您是使对象成为值类型还是引用类型。
考虑到不可变类型在行为上的这种模糊区别,这留给我们什么标准来决定是将不可变类型设为引用类型还是值类型?
此外,由于不可变强调值与变量,不可变类型是否应该始终实现值语义?
【问题讨论】:
标签: c# .net immutability