我最初是从这个地址接过来的: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; }
}
答案 0 :(得分:4)
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
字段的副本,当你的修改超出范围时你的修改就被丢弃了)。
avoid mutable structs like the plague这是一个很好的理由。
答案 1 :(得分:1)
这是因为结构是值类型,当你传递它时会创建一个副本。使用字段,您将访问结构的真实版本,而对于属性,它将返回它的副本。然后,您可以更改此副本,然后将该副本丢弃。
答案 2 :(得分:1)
链接代码中的注释解释了这一点......
将holder.Property作为副本检索并更改副本
换句话说,.SetValue(10)
上的holder.Property
适用于holder.Property
的副本,而非holder.Property
本身。
答案 3 :(得分:1)
当您访问持有者的属性时,您正在创建原始结构的副本,然后在副本上调用方法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方法时,会创建原始文件的副本,并且该方法返回的副本不是原始文件