2010-05-26 52 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超载,串>不会继续递归。

然而,正如你会注意到,有很多的类型检查和铸造回事,和字典<字符串,对象> 气味严重 - 它本质上违背了仿制药的目的。

我建议你看看访问者模式代替。