C# 在C语言中遍历任意字典树结构#

C# 在C语言中遍历任意字典树结构#,c#,generics,recursion,C#,Generics,Recursion,我正在尝试编写一个递归C#函数,该函数将在IDictionary形式的通用词典上运行,T是另一个IDictionary或字符串 我第一次失败的尝试是这样的: public string HandleDict(IDictionary<string, string> dict){ // handle the leaf-node here } public string HandleDict<T>(IDictionary<string, IDictionary&

我正在尝试编写一个递归C#函数,该函数将在
IDictionary
形式的通用词典上运行,
T
是另一个
IDictionary
或字符串

我第一次失败的尝试是这样的:

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]);
    }
}
公共字符串句柄(IDictionary dict){
//在这里处理叶节点
}
公共字符串处理ICT(IDictionary dict){
//环游儿童
foreach(dict.Keys中的字符串键){
HandleDict(dict[key]);
}
}

我还尝试了
HandleDict(IDictionary)的变体,其中T:IDictionary
,但这也不太管用。我知道我想做的事情可以通过自定义类作为参数而不是字典来实现,而且我的尝试在概念上是有缺陷的(泛型函数中的递归没有尽头)。我仍然想知道是否有一种方法可以实现我在这里想要的功能,只使用泛型IDictionary。

为了将字典或字典作为值存储在字典中,您需要将字典声明为Dictionary类型

公共字符串句柄(IDictionary dict)
{
foreach(dict中的KeyValuePair kvp)
{
然后,您需要检查每个值是否是字符串、另一个字典或另一个字典——C#在编译时执行重载解析,而不是在运行时

        var leaf = kvp.Value as IDictionary<string, string>;
        if (leaf != null)
        {
            HandleDict(leaf);
        }
        else
        {
            HandleDict((IDictionary<string, object>)kvp.Value);
        }
    }
}
var leaf=kvp.Value作为IDictionary;
如果(叶!=null)
{
HandleDict(leaf);
}
其他的
{
HandleDict((IDictionary)kvp.值);
}
}
}
递归将在到达叶时结束,因为字典的HandleDict重载不会继续递归

然而,正如您所注意到的,有很多类型检查和转换正在进行,而且字典的味道很难闻,它基本上违背了泛型的目的

我建议您改为查看访问者模式。

C#type系统的功能不足以表示您需要在类型系统中执行此操作的那种“更高”的泛型类型。考虑Haskell或F.*,如果你需要一个语言更丰富的泛型类型系统。
在C#4中,使用“动态”功能可以做你想做的事情,但我建议不要这样做。这样做基本上会在运行时再次启动编译器。我不会求助于运行时类型分析,而是会花一些时间重新考虑使用字典的决定。我怀疑对于您手头的实际任务,有更好的数据结构。描述该任务,我们将看看是否有更好的数据结构。

这样的字典不是不可实例化的,因为它始终是您定义的开放类型吗?该任务是一个字典到JSON转换例程,提供了一种从C代码生成任意JSON数据的简单方法(我们使用的是ASP.NET 2.0,没有访问JavascriptSerializer类的权限)。
        var leaf = kvp.Value as IDictionary<string, string>;
        if (leaf != null)
        {
            HandleDict(leaf);
        }
        else
        {
            HandleDict((IDictionary<string, object>)kvp.Value);
        }
    }
}