【问题标题】:Setting Property Doesn't Set Its Inner Property设置属性不设置其内部属性
【发布时间】:2014-04-23 05:00:50
【问题描述】:

我最初是从这个地址获取的:http://csharpindepth.com/articles/chapter8/propertiesmatter.aspx,但由于某种原因,我无法理解它。有人可以解释一下为什么 Console.WriteLine(holder.Property.Value);输出 0。

void Main()
{
    MutableStructHolder holder = new MutableStructHolder();
    holder.Field.SetValue(10);
    holder.Property.SetValue(10);
    Console.WriteLine(holder.Field.Value); // Outputs 10
    Console.WriteLine(holder.Property.Value); // Outputs 0
}

struct MutableStruct
{
    public int Value { get; set; }

    public void SetValue(int newValue)
    {
        Value = newValue;
    }
}

class MutableStructHolder
{
    public MutableStruct Field;
    public MutableStruct Property { get; set; }
}

【问题讨论】:

  • { 得到;放; } 是问题所在。如果我使用 public MutableStruct Property ;这个输出 10 和 10
  • 因为属性是用隐藏的 get/set 方法实现的,而结构是通过 getter 的值返回的。因此,您对属性所做的任何修改都不会在属性包装的字段上进行。

标签: c#


【解决方案1】:
class MutableStructHolder
{
    public MutableStruct Field;
    public MutableStruct Property { get; set; }
}

相当于

class MutableStructHolder
{
    public MutableStruct Field;

    private MutableStruct _Property;
    public MutableStruct Property { 
       get { return _Property; }
       set { _Property = value; }
    }
}

相当于:

class MutableStructHolder
{
    public MutableStruct Field;

    private MutableStruct _Property;
    public MutableStruct getProperty() { 
       return _Property;
    }
    public void setProperty(MutableStruct value) { 
       _Property = value;
    }
}

所以,当你这样做时:

holder.Property.SetValue(10);

你实际上正在这样做:

holder.getProperty().SetValue(10);

相当于:

MutableStruct temp = holder.getProperty(); 
temp.SetValue(10);

由于结构是值类型,temp 实际上是底层_Property 字段的副本,当超出范围时(立即)您的修改会被丢弃。 p>

这是avoid mutable structs like the plague 的充分理由。

【讨论】:

  • 啊,你也打败了我吧。可变结构可能是一个杀手。我打算链接到那个问题。
  • 是的,我之前已经链接过几次了——几乎和floating-point-gui.de一样频繁
【解决方案2】:

这是因为结构是值类型,当你传递它时,它会创建一个副本。使用字段,您正在访问结构的真实版本,而使用属性,它返回它的副本。然后您更改此副本,然后将其丢弃。

【讨论】:

  • @SimonWhitehead 抱歉,已修复。
【解决方案3】:

链接代码中的注释解释了这一点......

检索 holder.Property 作为副本并更改副本

换句话说,holder.Property 上的.SetValue(10) 适用于holder.Property副本,而不是holder.Property 本身。

【讨论】:

    【解决方案4】:

    当您访问 holder 的属性时,您正在创建原始结构的副本,然后在副本上调用方法 SetValue

    下面的代码在功能上会做同样的事情

    //First create a copy of the original
    var property = new MutableStruct();
    property.Value = holder.Property.Value;
    //That's not how the copy is actually created but the result is the same
    
    //set the value on the copy
    property.SetValue(10);
    
    //print the value of the original
    Console.WriteLine(holder.Property.Value);
    

    这发生在属性上,因为属性本​​质上是方法。当您调用 get 方法时,会创建原始副本,并且该副本是该方法返回的副本,而不是原始副本

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-12
      • 1970-01-01
      • 1970-01-01
      • 2018-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多