结构的不变性

Joa*_*nge 30 .net c# struct immutability

可能重复:
为什么可变结构是邪恶的?

我在很多地方阅读它,包括在这里最好将结构化为不可变的.

这背后的原因是什么?我看到许多微软创建的结构是可变的,就像xna中那样.可能在BCL还有更多.

不遵守本指南的利弊是什么?

Mar*_*ell 43

结构应该代表价值.值不会改变.12号是永恒的.

但是,请考虑:

Foo foo = new Foo(); // a mutable struct
foo.Bar = 27;
Foo foo2 = foo;
foo2.Bar = 55;
Run Code Online (Sandbox Code Playgroud)

现在foo.Bar和foo2.Bar是不同的,这通常是意料之外的.特别是在类似属性的场景中(幸运的是编译器检测到了这一点).还有收藏品等; 你怎么理智地改变他们?

使用可变结构,数据丢失太容易了.

  • 无论答案是什么(我不知道),你都不应该让性能问题胜过良好的设计_unless_这是一个瓶颈而且一个分析器告诉你这是问题的根源. (8认同)
  • @Henk =那是不同的.我没有**重新分配*foo2; 我更新了它.例如,我不说i.Sign =!i.Sign to*update*i; 我用i = -i重新分配它; ...重新分配它与更新属性非常不同. (5认同)
  • 我怀疑你是否注意到标准应用程序的不同之处.可能会有一些*非常专业的*案例,你会注意到,但*对于一般指导*,不可变的胜利. (2认同)

Jon*_*eet 17

最重要的是,事情并不像你期望的那样 - 特别是如果可变性来自直接值和其中的引用类型的混合.

老实说,当我们看到人们在使用可变结构时看到人们在新闻组中提出的所有奇怪问题时,我不记得了我的头脑 - 但这些原因确实存在.可变结构导致问题.远离.

编辑:我刚刚发现了一篇关于这个主题的电子邮件.它详细阐述了一下:

  • 这在哲学上是错误的:结构应该代表某种基本价值.这些基本上是不可改变的.您无法更改数字5.您可以将变量的值从5更改为6,但是您不会在逻辑上对值本身进行更改.

  • 这实际上是一个问题:它创造了许多奇怪的情况.如果它通过接口可变,那就特别糟糕.然后您可以开始更改盒装值.伊克.我看过很多新闻组帖子,这些帖子是由于人们试图使用可变结构并遇到问题.我看到一个非常奇怪的LINQ示例,它失败了,因为它List<T>.Enumerator是一个结构,例如.

  • 真正的程序员不会睡觉,他们只是偶尔放弃剩余的时间段.;) (4认同)
  • 你还睡觉吗?XDDD (2认同)

Mat*_*vey 10

我经常在我的(性能关键)项目中使用可变结构 - 我不会遇到问题,因为我理解复制语义的含义.据我所知,主理人的主张不变的结构是这样的人谁明白的影响不能让自己陷入困境.

这不是一件可怕的事情 - 但我们现在处于危险之中,因为它变成了"福音真理",事实上有时候它是合法地使结构变得可变的最佳选择.与所有事情一样,规则也有例外.


Jon*_*len 5

操作比可变结构更便宜,这就是为什么你经常在高性能代码中看到它,比如图形处理程序.

不幸的是,可变结构不能很好地与对象和属性一起使用,修改结构的副本而不是结构本身太容易了.因此,它们不适合您的大多数代码.

PS为了避免复制可变结构的成本,它们通常以数组的形式存储和传递.


Mic*_*ows 5

技术原因是可变结构似乎能够做他们实际上没做的事情.由于设计时语义与引用类型相同,因此开发人员会感到困惑.这段代码:

public void DoSomething(MySomething something)
{
    something.Property = 10;
}
Run Code Online (Sandbox Code Playgroud)

行为完全不同取决于if MySomething是a struct还是a class.对我来说,这是一个引人注目的,但不是最引人注目的原因.如果查看DDDValue Object,可以看到应该如何处理结构的连接.DDD中的值对象最好表示为.Net中的值类型(因此也就是结构).因为它没有身份,所以不能改变.

从您的地址等方面考虑这一点.您可以"更改"您的地址,但地址本身并未更改.实际上,您已为您分配了新地址.从概念上讲,这是有效的,因为如果你真的改变了你的地址,你的室友也必须搬家.


Erg*_*wun 5

您已经要求遵循指南的优点和缺点,即结构应该是不可变的.

缺点:缺点在现有答案中得到很好的解释,并且所描述的大多数问题都是由于相同的原因 - 由于结构的值语义而导致的意外行为.

优点:使用可变结构的主要优点可能是性能.显然,这个建议伴随着关于优化的所有常见警告:确保部分代码需要进行优化,并确保任何更改都能通过分析实际优化代码的性能.

有关讨论何时可能需要使用可变结构的优秀文章,请参阅Rico Mariani 关于基于价值的编程性能测验(或更具体地说,答案).