2010-05-26 55 views
2

我想寫一個遞歸C#函數,它將操作IDictionary<string, T>形式的通用字典,其中T是另一個IDictionary<string, T>或字符串。遍歷C#中的任意字典樹結構

我第一次失敗的嘗試看起來是這樣的:的HandleDict<T>(IDictionary<string, T>) where T : IDictionary<string, T>

public string HandleDict(IDictionary<string, string> dict){ 
    // handle the leaf-node here 
} 

public string HandleDict<T>(IDictionary<string, IDictionary<string, T>> dict){ 
    // loop through children 
    foreach(string key in dict.Keys){ 
     HandleDict(dict[key]); 
    } 
} 

我也試過變種,但也完全不是那麼回事。我知道我想要做的事可以通過一個自定義類作爲參數而不是字典來實現,並且我的嘗試在概念上有缺陷(泛型函數中的遞歸沒有結束)。我仍然想知道是否有一種方法可以使用普通的IDictionaries來實現我想要的功能。

+0

難道這樣一本詞典是不可實例無論如何,因爲它總是爲你定義它的開放式? – lesscode 2010-05-26 22:03:46

回答

3

C#的類型系統是沒有強大到足以代表的那種,你需要做到這一點的類型系統正確的「高級」泛型類型的。考慮Haskell或F#,如果您需要使用更豐富的泛型類型系統的語言。

這是可以做到你在使用「動態」特性C#4想要什麼,但我會建議反對。這樣做基本上可以在運行時再次啓動編譯器。我會花一些時間重新考慮首先使用字典的決定,而不是訴諸運行時類型分析。我懷疑你的實際任務有更好的數據結構。描述這個任務,我們會看看是否有更好的數據結構。

+0

的任務是一本字典到JSON的轉換程序提供一個簡單的方法來從C#代碼中的任意JSON數據(我們使用ASP.NET 2.0和沒有進入JavascriptSerializer類)。 – Rudism 2010-05-27 12:11:57

4

爲了存儲字典<字符串,字符串>或字典<字符串, >如在字典中的值,你需要申報的字典是型詞典<字符串,對象 >。

public string HandleDict(IDictionary<string, object> dict) 
{ 
    foreach (KeyValuePair<string, object> kvp in dict) 
    { 

然後,你需要檢查每一個值,如果它是一個字符串或其他字典<字符串,字符串>或其他字典<字符串,對象> - C#進行編譯時重載決議,不在運行時!到達葉時

 var leaf = kvp.Value as IDictionary<string, string>; 
     if (leaf != null) 
     { 
      HandleDict(leaf); 
     } 
     else 
     { 
      HandleDict((IDictionary<string, object>)kvp.Value); 
     } 
    } 
} 

遞歸就結束了,因爲字典<串HandleDict超載,串>不會繼續遞歸。

然而,正如你會注意到,有很多的類型檢查和鑄造回事,和字典<字符串,對象> 氣味嚴重 - 它本質上違背了仿製藥的目的。

我建議你看看訪問者模式代替。