C# 结构的不变性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/608542/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 10:09:44  来源:igfitidea点击:

Immutability of structs

c#.netstructimmutability

提问by Joan Venge

Possible Duplicate:
Why are mutable structs evil?

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

I read it in lots of places including here that it's better to make structs as immutable.

我在很多地方都读过它,包括这里,最好将结构设为不可变。

What's the reason behind this? I see lots of Microsoft-created structs that are mutable, like the ones in xna. Probably there are many more in the BCL.

这背后的原因是什么?我看到很多 Microsoft 创建的结构是可变的,比如 xna 中的结构。BCL中可能还有更多。

What are the pros and cons of not following this guideline?

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

采纳答案by Marc Gravell

Structs should represent values. Values do not change. The number 12 is eternal.

结构应该代表。价值观不会改变。数字12是永恒的。

However, consider:

但是,请考虑:

Foo foo = new Foo(); // a mutable struct
foo.Bar = 27;
Foo foo2 = foo;
foo2.Bar = 55;

Now foo.Bar and foo2.Bar is different, which is often unexpected. Especially in the scenarios like properties (fortunately the compiler detect this). But also collections etc; how do you ever mutate them sensibly?

现在 foo.Bar 和 foo2.Bar 是不同的,这往往是出乎意料的。特别是在像属性这样的场景中(幸运的是编译器检测到了这一点)。还有收藏品等;你如何明智地改变它们?

Data loss is far too easy with mutable structs.

对于可变结构,数据丢失太容易了。

回答by froh42

When you copy structs around you copy their contents, so if you modify a copied version the "original" will not be updated.

当您复制周围的结构时,复制它们的内容,因此如果您修改复制的版本,“原始”将不会更新。

This is a source for errors, since even if you know that you fall into the trap of copying a struct (just by passing it to a method) and modifying the copy.

这是错误的来源,因为即使您知道自己陷入了复制结构(仅通过将其传递给方法)和修改副本的陷阱。

Just happened to me againlast week, kept me an hour searching for a bug.

上周发生在我身上,让我花了一个小时寻找错误。

Keeping structs immutable prevents that ...

保持结构不可变可以防止......

Other than that you need to make sure you have a really good reason to use structs in the first place - "optimization" or "I want something that allocates quickly on the stack" does not count as an answer. Marshaling or things where you depend on layout - ok, but you should not typically keep those structs around for very long, they are values not objects.

除此之外,您首先需要确保有充分的理由使用结构体——“优化”或“我想要在堆栈上快速分配的东西”不算作答案。编组或依赖于布局的事物 - 好的,但通常不应将这些结构保留很长时间,它们是值而不是对象。

回答by Randolpho

the reason you should make structs immutable is that they're ValueTypes, meaning that they are copied every time you pass them to a method.

您应该使结构不可变的原因是它们是ValueTypes,这意味着每次将它们传递给方法时都会复制它们。

So if, for example, you had a property that returned a struct, modifying the value of a field on that struct would be worthless, because the getter would return a copyof the struct, rather than a reference to the struct. I've seen this done in code, and it's often difficult to catch.

因此,例如,如果您有一个返回结构的属性,则修改该结构上字段的值将毫无价值,因为 getter 将返回该结构的副本,而不是对该结构的引用。我已经在代码中看到过这种情况,而且通常很难捕捉到。

If you design your structs for immutability, you help the programmer avoid these mistakes.

如果您为不变性设计结构,您可以帮助程序员避免这些错误。

回答by Jon Skeet

The big con is that things don't behave how you expect them to - particularly if the mutability comes from a mixture of the direct value and a reference type within it.

最大的缺点是事情不会像你期望的那样表现 - 特别是如果可变性来自直接值和其中的引用类型的混合。

To be honest, I can't remember off the top of my head all the weird problems I've seen people come up with in newsgroups when they've used mutable structs - but those reasons certainly exist. Mutable structs cause problems.Stay away.

老实说,当人们使用可变结构时,我无法记住我在新闻组中看到的所有奇怪问题——但这些原因确实存在。可变结构会导致问题。远离。

EDIT: I've just found an email I wrote a while ago on this topic. It elaborates just a little bit:

编辑:我刚刚找到了我前段时间写的关于这个主题的电子邮件。它详细说明了一点:

  • It's philosophically wrong: a struct should represent some sort of fundamental value. Those are basically immutable. You don't get to change the number 5. You can change a variable's value from 5 to 6, but you don't logically make a change to the value itself.

  • It's practically a problem: it creates lots of weird situations. It's particularly bad if it's mutable via an interface. Then you can start changing boxed values. Ick. I've seen a lot of newsgroup posts which are due to people trying to use mutable structs and running into issues. I saw a very strange LINQ example which was failing because List<T>.Enumeratoris a struct, for example.

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

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

回答by Guffa

A struct should generally represent a single unity of some kind. As such it doesn't make much sense to change one of the properties of the value, it makes more sense to create a completely new value if you want a value that is different somehow.

一个结构体通常应该代表某种单一的统一体。因此,更改值的一个属性没有多大意义,如果您想要一个以某种方式不同的值,则创建一个全新的值更有意义。

The semantics gets simpler when using immutable structs, and you avoid pitfalls like this:

使用不可变结构时语义会变得更简单,并且您可以避免这样的陷阱:

// a struct
struct Interval {
   int From { get; set; }
   int To { get; set; }
}

// create a list of structs
List<Interval> intervals = new List<Interval>();

// add a struct to the list
intervals.Add(new Interval());

// try to set the values of the struct
intervals[0].From = 10;
intervals[0].To = 20;

The result is that the struct in the list is not changed at all. The expression Interval[0] copies the value of the struct from the list, then you change the property of the temporary value, but the value is never put back in the list.

结果是列表中的结构根本没有改变。表达式 Interval[0] 从列表中复制结构体的值,然后您更改临时值的属性,但该值永远不会放回列表中。

Edit: Changed the example to use a list instead of an array.

编辑:将示例更改为使用列表而不是数组。

回答by Jonathan Allen

There is nothing cheaper to manipulate than a mutable struct, which is why you often see it in high performance code like the graphics processing routines.

没有什么比可变结构更便宜的操作了,这就是为什么您经常在高性能代码(如图形处理例程)中看到它的原因。

Unfortunately mutable structs don't play well with objects and properties, it is way too easy to modify a copy of a stuct instead of the struct itself. Thus they aren't appropriate for most of your code.

不幸的是,可变结构不能很好地处理对象和属性,修改结构的副本而不是结构本身太容易了。因此它们不适用于您的大部分代码。

P.S. To avoid the cost of copying mutable structs, they are usually stored and passed in arrays.

PS 为了避免复制可变结构的成本,它们通常被存储并在数组中传递。

回答by Michael Meadows

The technical reason is that mutable structs appearto be able to do things that they don't actually do. Since the design-time semantics are the same as reference types, this becomes confusing for developers. This code:

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

public void DoSomething(MySomething something)
{
    something.Property = 10;
}

Behaves quite differently depending on if MySomethingis a structor a class. To me, this is a compelling, but not the most compelling reason. If you look at DDD's Value Object, you can see the connection to how structs should be treated. A value object in DDD can be best represented as a value type in .Net (and therefore a struct). Because it has no identity, it can't change.

行为完全不同取决于 ifMySomething是 astruct还是 a class。对我来说,这是一个令人信服的理由,但不是最令人信服的理由。如果您查看DDDValue Object,您可以看到与应如何处理结构的联系。DDD 中的值对象可以最好地表示为 .Net 中的值类型(因此是结构)。因为它没有身份,所以无法改变。

Think of this in terms of something like your address. You can "change" your address, but the address itself hasn't changed. In fact, you have a new address assigned to you. Conceptually, this works, because if you actually changedyour address, your roommates would have to move too.

可以根据您的地址之类的内容来考虑这一点。您可以“更改”您的地址,但地址本身并没有改变。事实上,你有一个新地址分配给你。从概念上讲,这是有效的,因为如果您真的更改了地址,您的室友也必须搬家。

回答by Ergwun

You have asked for the pros and cons of notfollowing the guideline that structs should be immutable.

您已经询问了遵循结构应该是不可变的准则的利弊。

Cons:The cons are well covered in existing answers, and most problems described are due to the same cause - unexpected behaviour due to structs' value semantics.

缺点:现有答案中已经很好地涵盖了缺点,并且描述的大多数问题都是由于相同的原因 -由于结构的值语义导致的意外行为

Pros:The main pro of using mutable structs can be performance. Obviously, this advice comes with all the usual caveats about optimisations: make sure that part of your code needsto be optimised and make sure any changes do actually optimise your code's performance via profiling.

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

For an excellent article discussing when you might want to use mutable structs, see Rico Mariani's Performance Quiz on Value-Based Programming(or more specifically, the answers).

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

回答by MattDavey

I use mutable structs often in my (performance critical) project - and I don't run into problems, because I understand the implications of copy semantics. As far as I can tell, the main reason people advocate immutable structs is so that people who don'tunderstand the implications can't get themselves in trouble.

我经常在我的(性能关键)项目中使用可变结构 - 我没有遇到问题,因为我理解复制语义的含义。据我所知,人们提倡不可变结构的主要原因是理解其含义的人不会陷入困境。

That's not such a terrible thing - but we're in danger now of it becoming "the gospel truth", when in fact there are times where it is legitimately the best option to make a struct mutable. Like with all things, there are exceptions to the rule.

这并不是什么可怕的事情——但我们现在正处于它成为“福音真理”的危险之中,而事实上,有时它是使结构可变的合法最佳选择。与所有事物一样,规则也有例外。