2012-09-19 133 views
4

我有一個需要存儲在集合中的結構。該結構具有返回字典的屬性。從另一個集合中訪問結構集合屬性

public struct Item 
{ 
    private IDictionary<string, string> values; 
    public IDictionary<string, string> Values 
    { 
     get 
     { 
      return this.values ?? (this.values = new Dictionary<string, string>()); 
     } 
    } 
} 

public class ItemCollection : Collection<Item> {} 

當測試時我發現如果我將項目添加到集合,然後嘗試訪問字典,結構值屬性永遠不會更新。

var collection = new ItemCollection { new Item() }; // pre-loaded with an item 
collection[0].Values.Add("myKey", "myValue"); 
Trace.WriteLine(collection[0].Values["myKey"]); // KeyNotFoundException here 

但是,如果我先加載項目,然後將其添加到集合值字段保持。

var collection = new ItemCollection(); 
var item = new Item(); 
item.Values.Add("myKey", "myValue"); 
collection.Add(item); 
Trace.WriteLine(collection[0].Values["myKey"]); // ok 

我已經決定,一個結構是這種類型的錯誤的選項,並使用一個類時,不會出現問題,但我很好奇什麼是兩種方法之間的不同。任何人都可以解釋發生了什麼?

+1

msdn doc:這是一個msdn示例http://msdn.microsoft.com/en-us/library/vstudio/8b0bdca4.aspx – Cybermaxs

回答

1

正如之前提到的,將struct Item更改爲class Item。當您使用struct時,表達式collection[0]不會返回對new ItemCollection { new Item() }中創建的對象的引用,而是會創建它的副本並將其提供給您。

+0

你可以在這個節目上展示嗎? –

2

更改你的結構是一個類,而不是:

public class Item {} 

現在我不是那熟悉的內臟,但結構是值類型,一類是引用類型,而且我相信,有在那裏是邏輯,這解釋了爲什麼在運行第一個代碼示例時出現異常。

我希望有人能夠給你一個更徹底的答案,但現在,只需將結構更改爲一個類。

+0

正如你可以在這裏看到的(http://stackoverflow.com/questions/521298/when-to-use-struct-in-c),我認爲有一個這種情況的結構並不理想。 – Cybermaxs

1

「Item」是一個值項。這意味着,如果您訪問該集合,則會創建一個副本。所有的操作都在該副本

collection[0].Values.Add("myKey", "myValue"); 

這裏一份拷貝,則該值get訪問的第一個項目的完成創建一個新的實例,該實例存儲在副本,然後加入該項目。那麼副本被銷燬。

一個解決方法是建立在價值觀上的結構

public struct Item 
{ 
    private IDictionary<string, string> values = new Dictionary<string, string>(); 
    public IDictionary<string, string> Values 
    { 
     get 
     { 
      return this.values; 
     } 
    } 
} 

的創建字典直接,如果你訪問集合,一個副本。但此副本包含對原始值相同值字典的引用。所以原始字典被修改

+0

謝謝。你看起來似乎是正確的,但是編譯器不會允許賦值到values字段 - 「結構中不能有實例字段初始值設定項」 – paddyb

+0

結構可以有一個構造函數。 –

+0

@Baboon是真的,但它仍然不能分配到值域 – paddyb

相關問題