ser*_*0ne 5 .net c# struct mutable immutability
我最近一直在阅读很多关于价值类型和参考类型及其差异的文献.这个问题围绕着价值类型的可变性和不变性这一主题.
基于我所读到的,似乎.NET中的值类型应该以它们不可变的方式编写; 也就是说,一旦为它们分配了一个值,该类型在内存中的值永远不会改变.只有该类型的后续副本可以在内存中构造新实例,并使用基于原始值的新值.似乎.NET中的可变性是邪恶的.
为了澄清对不变性的理解(为了我自己的理智和其他人),我在下面证明了这一点:
DateTime并且TimeSpan是不可变结构的示例,因为一旦将值赋给实例,该实例值就不会改变,这通过只读属性很明显:
DateTime dt = new DateTime();
DateTime newdt = dt.AddDays(2); // Okay, new value stored in newdt
newdt.Year = 1945; // Error, cannot write to readonly property
Run Code Online (Sandbox Code Playgroud)
然而,当看到原始类型时,不变性可能会令人困惑Int32,Double或者Char,因为类型似乎是可变的,但我的直觉是实际上,通过CLR透明地处理不变性; 以下是一些操作(我在一些非常基本的x86中进行了评论,以了解如何根据原始类型处理不变性)
int x = 0;
// xor eax, eax; 'clear register to 0
// push eax; 'push eax (0) onto the stack
x = 5;
// pop eax; 'pop stack (0) into eax
// mov eax, 5; 'eax = 5
// push eax; 'push eax (5) onto the stack
x++;
// pop eax; 'pop stack (5) into eax
// add eax, 1; 'eax = 5 + 1
// push eax; 'push eax (6) onto the stack
Run Code Online (Sandbox Code Playgroud)
到目前为止一切顺利; 微软似乎在将不可变性实现到其价值类型方面做得很好; 但后来我们开始发现坏苹果,并且让可变性看起来不错的细微差别让开发人员陷入虚假的安全感!
我在谈论System.Drawing命名空间中的Point,Size,Rectangle(以及其他几个).
突然间,我们被赋予了通过它的属性来改变值类型的能力,并且我有一个关于为什么这是可能的理论; 以下面的代码为例
Point p = new Point();
p.X = 100;
p.Y = 200;
// Immutability (had it been implemented here) might infer the following usage
Point p = new Point(100, 200);
Point p2 = p.AddXY(200, 300);
Run Code Online (Sandbox Code Playgroud)
然而,如上所述,我有一个关于为什么这些结构是可变的理论:
最后我的问题:
可变性问题不是价值与参考类型之一.两者都有例子.以System.String不可变类为例,以及作为System.Drawing.Point可变结构示例的示例.
Mutable与immutable是基于类型用法的设计决策.无论是引用还是值类型,都是另一个不依赖于前者的设计决策.