遍历C#中的任意字典树结构

时间:2010-05-26 21:35:33

标签: c# generics recursion

我正在尝试编写一个递归C#函数,该函数将对IDictionary<string, T>形式的通用字典进行操作,其中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]);
    }
}

我也尝试了HandleDict<T>(IDictionary<string, T>) where T : IDictionary<string, T>的变体,但这也不太合适。我知道我想要做的事情可以通过自定义类作为参数而不是字典来实现,并且我的尝试在概念上是有缺陷的(通用函数中的递归没有结束)。我仍然想知道是否真的有办法在这里使用通用IDIC来做我想要的。

2 个答案:

答案 0 :(得分:4)

为了存储Dictionary&lt; string,string&gt;或字典&lt; string,??&gt;作为字典中的值,您需要将字典声明为Dictionary&lt; string, object &gt;类型。

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

然后你需要检查每个值,如果它是一个字符串或另一个字典&lt; string,string&gt;或另一个字典&lt; string,object&gt; - C#在编译时执行重载决策,而不是在运行时执行!

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

递归将在到达叶子时结束,因为HandleDict重载了Dictionary&lt; string,string&gt;不会继续递归。

然而,正如您将注意到的,有很多类型检查和强制转换,以及Dictionary&lt; string,object&gt; 闻起来很糟糕 - 它基本上违背了仿制药的目的。

我建议你看一下访客模式

答案 1 :(得分:3)

C#类型系统的功能不足以表示在类型系统中需要执行此操作所需的“更高”泛型类型。如果您需要具有更丰富的泛型类型系统的语言,请考虑使用Haskell或F#。

可以使用“动态”功能在C#4中执行您想要的操作,但我建议不要使用它。这样做基本上会在运行时再次启动编译器。我花了一些时间重新考虑首先使用字典的决定,而不是诉诸运行时类型分析。我怀疑手头的实际任务有更好的数据结构。描述该任务,我们将看看是否有更好的数据结构。