首页 文章

.NET中的值类型,不变性(好)和可变性(邪恶)[重复]

提问于
浏览
5

这个问题在这里已有答案:

我最近一直在阅读很多关于Value Types & Reference Types的文献,以及他们的不同之处 . 这个问题围绕着 mutabilityimmutability 的值类型主题 .

基于我所读到的,似乎.NET中的值类型应该以它们不可变的方式编写;也就是说,一旦为它们分配了一个值,该类型在内存中的值永远不会改变 . 只有该类型的后续副本可以在内存中构造新实例,并使用基于原始值的新值 . 似乎.NET中的可变性是邪恶的 .

为了澄清对不变性的理解(为了我自己的理智和其他人),我在下面证明了这一点:

DateTimeTimeSpanimmutable 结构的示例,因为一旦将值分配给实例,该实例值就不会改变,这通过只读属性很明显:

DateTime dt = new DateTime();
DateTime newdt = dt.AddDays(2); // Okay, new value stored in newdt
newdt.Year = 1945; // Error, cannot write to readonly property

然而,当看到诸如 Int32DoubleChar 等原始类型时,不变性可能会令人困惑,因为这些类型似乎是可变的,但我的直觉是,实际上,不变性是通过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

到目前为止一切顺利;微软似乎在将不可变性实现到其 Value 类型方面做得很好;但后来我们开始发现坏苹果,并且让可变性看起来不错的细微差别让开发人员陷入虚假的安全感!

我在讨论System.Drawing名称空间中的PointSizeRectangle(以及其他几个) .

突然间,我们被赋予了通过它的属性来改变值类型的能力,并且我有一个关于为什么这是可能的理论;以下面的代码为例

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);

然而,如上所述,我有一个关于为什么这些结构是可变的理论:

  • 微软只是想让这些结构更容易使用 .

  • 它们可与本机GDI / GDI调用互操作,因此它们的行为是围绕其本机C / C对应物设计的 .

最后我的问题:

  • 我是否已完全涵盖并理解不变性和可变性?

  • 开发人员是否应该通常 Build 不可变结构?

  • 何时可以构建可变结构?

2 回答

  • 6

    嗯......这可能会很快关闭,但这是我对此的看法 .

    • 是的,似乎你在理解不变性和可变性 .

    • 应该是个大字 . 开发人员应该意识到这些差异,要足够了解他们的交易,并且要有自己的常识:我需要从这个特定的结构中得到什么 .

    • 可以接受吗?我猜你什么时候需要它 . 你何时需要一个问题是一个完全不同的问题 .

    通常使用结构来保存一些属性或基元类型 . 有些文章关于你应该和不应该在你的结构中有什么,以便它们在堆或堆栈上结束,但这不在这里 .
    如果您有令人信服的理由使用可变结构,并且您将其记录下来以便下一个开发人员知道原因,那就没关系 .
    如果恰恰相反,你真的不知道可接受的是什么:) .

  • 2

    可变性问题不是 Value 与参考类型之一 . 两者都有例子 . 将 System.String 作为不可变类的示例以及 System.Drawing.Point 的示例作为可变结构的示例 .

    Mutable与immutable是基于类型用法的设计决策 . 无论是引用还是值类型,都是另一个不依赖于前者的设计决策 .

相关问题