2017-02-16 63 views
3

我想構建一個字典,其中鍵是值對象的屬性。不過,我想在字典的add方法中構造value對象。有沒有辦法做到這一點,而不使用中間變量?將元素添加到字典中,其中鍵的屬性值爲

例如,我想要做以下事情,但當然,關鍵值在需要時不可用。

Dictionary<int,SomeComplexObject> dict = new Dicionary<int,SomeComplexObject>{ 
    {someComplexObject.Key, new SomeComplexObject {Key = 1, Name = "FooBar"}, 
    {someComplexObject.Key, new SomeComplexObject {Key = 2, Name = "FizzBang"} 
}; 

我必須做這種醜陋的方式:

Dictionary<int,SomeComplexObject> dict = new Dicionary<int,SomeComplexObject>(); 
SomeComplexObject value1 = new SomeComplexObject{Key=1,Name = "FooBar"}; 
dict.Add(value1.Key,value1); 
SomeComplexObject value2 = new SomeComplexObject{Key=2,Name = "FizzBang"}; 
dict.Add(value.Key,value2); 

我不認爲這是因爲我不是關鍵專門問同樣的問題作爲 How to use an object's identity as key for Dictionary<K,V>

的字典,但是如果有一種方法可以在對象未被創建時訪問對象屬性,直到稍後在方法參數列表中。

+0

評論[已存檔在聊天](http://chat.stackoverflow.com/rooms/136085/discussion-on-question-by-automatic-add-element-to-dictionary-where-key-is-prope) 。 –

回答

2

雖然原來的問題似乎不是很清楚,但在評論中的討論後,我認爲其他人是正確的,我選擇的重複可能不是正確的。我也有責任提供一個答案,因爲已經結束了這個問題,我干涉了別人提出自己答案的能力,可能會拖延甚至消除您獲得所需答案的機會。

所有這一切說,我也不認爲擴展方法(如評論中提出的)真的是你想要在這裏,因爲它只是一個部分的解決方案。即你將不得不爲你想要使用的每種字典值類型編寫一個新的擴展方法,這就否定了尋求一個通用解決方案的全部要點。

相反,在我看來,你可能只是想要類型的子類來添加自己的自定義行爲。您可以通過一種通用的方式只做一次,這樣您就可以爲每種類型提供一個委託,這樣您就可以使用這種方式。

這將是這個樣子:

class KeyExtractorDictionary<TKey, TValue> : Dictionary<TKey, TValue> 
{ 
    private readonly Func<TValue, TKey> _extractor; 

    public KeyExtractorDictionary(Func<TValue, TKey> extractor) 
    { 
     _extractor = extractor; 
    } 

    public void Add(TValue value) 
    { 
     Add(_extractor(value), value); 
    } 
} 

你會使用它是這樣的:

class Data 
{ 
    public int Key { get; } 
    public string Name { get; } 

    public Data(int key, string name) 
    { 
     Key = key; 
     Name = name; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     KeyExtractorDictionary<int, Data> dictionary = 
      new KeyExtractorDictionary<int, Data>(d => d.Key) 
      { 
       new Data(1, "FooBar"), 
       new Data(2, "FizzBang") 
      }; 
    } 
} 

(我用Data作爲價值型類型,而不是T你似乎在你的問題中使用,以避免混淆類型名稱與通用類型參數。)

這樣,你只需要寫t他只上過一次課,不管你想用這種類型的字典有多少種不同的類型。然後,您可以將類構造函數傳遞給適用於當前字典值類型的鍵提取器委託。

請注意,通過這種方式,您還可以利用C#的集合初始化程序語法。由於你的新類型有一個Add()方法,它只爲每個字典條目取值,因此編譯器會將集合初始值設定項轉換爲正確的調用,以便將每個對象添加到字典中。

這允許一個字典,在該字典中,您仍然可以單獨使用鍵值檢索對象(使用自定義比較器將需要具有您所查找的相同鍵的值類型的實例),同時仍處理更廣泛不必在添加對象時明確指定密鑰以及通用性和重用性的擔憂。

0

你可以嘗試擴展方法,這是創傷小:

public static void AddByKey<TKey, T>(this Dictionary<TKey, T> dictionary, T item) 
{ 
    dictionary.Add(item.Key, item); 
} 

但要真正做到這一點正確的,你還需要一個接口來保護您免受類型,而Key屬性:

public interface ItemWithKey<TKey> 
{ 
    TKey Key { get; } 
} 

public static void AddByKey<TKey, T>(this Dictionary<TKey, T> dictionary, T item) 
    where T : ItemWithKey<TKey> 
{ 
    dictionary.Add(item.Key, item); 
} 

我現在沒有一個編譯器在我的手中,我無法測試此代碼,因此可能會出現小錯誤。如果您的代碼中存在大量情況,我希望您能夠理解並使用它。否則,我會建議您使用已有的難看的工作代碼。

相關問題