为什么当一个相同类中的字段没有时,结构中的字段会丢失其值?

des*_*scf 1 .net c# struct field

我有一个带有一个字段的结构,它失去了它的价值.我可以将字段声明为静态并解决问题.我也可以将struct更改为class(不改变任何其他内容),这也解决了问题.我只是想知道为什么会这样?

Dre*_*kes 5

结构按值传递.换句话说,当您传递结构时,您将传递其值的副本.因此,如果您获取值的副本并进行更改,则原始内容将保持不变.您更改了副本,而不是原始副本.

没有看到你的代码,我无法确定,但我认为这是正在发生的事情.

对于类而言,这不会发生,因为它们是通过引用传递的.

值得一提的是,这就是为什么结构应该是不可变的 - 也就是说,一旦它们被创建,它们就不会改变它们的价值.提供修改版本的操作将返回新结构.


编辑:在下面的评论中,@ supercat表明可变属性可以更方便.但是,结构上的属性设置器也可能导致奇怪的故障.这是一个可以让你惊讶的例子,除非你深刻理解结构是如何工作的.对我来说,这足以完全避免可变结构.

考虑以下类型:

struct Rectangle {
    public double Left { get; set; }
}

class Shape {
    public Rectangle Bounds { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

好的,现在想象一下这段代码:

myShape.Bounds.Left = 100;
Run Code Online (Sandbox Code Playgroud)

也许令人惊讶的是,这根本没有效果!为什么?让我们用更长但等效的形式重写代码:

var bounds = myShape.Bounds;
bounds.Left = 100;
Run Code Online (Sandbox Code Playgroud)

它更容易看到这里的如何Bounds被复制到一个局部变量,然后将其值被改变.但是在任何时候都没有Shape更新原始值.

这是非常有说服力的证据,使所有公共结构都不可改变.如果你知道你在做什么,可变的结构可以很方便,但我个人只有真正在这种形式的私人嵌套类使用它们.

正如@supercat指出的那样,替代方案有点不雅观:

myShape.Bounds = new Rectangle(100, myShape.Bounds.Top, 
                               myShape.Bounds.Width, myShape.Bounds.Height);
Run Code Online (Sandbox Code Playgroud)

有时候添加辅助方法会更方便:

myShape.Bounds = myShape.Bounds.WithLeft(100);
Run Code Online (Sandbox Code Playgroud)