2014-04-23 199 views
0

我原來從這個地址: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

{get;組; }是問題。如果我使用公共MutableStruct屬性;此輸出10和10 –

+4

由於屬性是使用隱藏的get/set方法實現的,並且結構是通過getter中的值返回的。因此,您對屬性所做的任何修改都不會在屬性包裝的字段上進行。 – Blorgbeard

回答

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

+0

啊,你也打敗了我吧。可變的結構可能是一個殺手。我會連接到這個問題。 –

+0

是的,我之前已經多次鏈接過它 - 幾乎和http://floating-point-gui.de/一樣多 – Blorgbeard

1

這是因爲結構是值類型,當您傳遞它時會創建副本。使用字段,您正在訪問結構的實際版本,而使用屬性時,它會返回它的副本。然後,您更改此副本,然後副本被丟棄。

+0

...但是OP在調用'Property.SetValue'以及... –

+0

@SimonWhitehead對不起,修正了它。 – Euphoric

1

中的鏈接代碼的註釋解釋了這個...

檢索holder.Property作爲副本,並更改​​副本

換句話說,在holder.Property.SetValue(10)適用於holder.Property的副本,而不是holder.Property本身。

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方法時,會創建一個原始副本,它是由方法返回的副本,而不是原始的