【问题标题】:Traversing through an arbitrary dictionary tree structure in C#在 C# 中遍历任意字典树结构
【发布时间】:2011-02-24 09:50:42
【问题描述】:

我正在尝试编写一个递归 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&lt;T&gt;(IDictionary&lt;string, T&gt;) where T : IDictionary&lt;string, T&gt; 的变体,但这也不太奏效。我知道我想做的事情可以通过自定义类作为参数而不是字典来实现,并且我的尝试在概念上存在缺陷(泛型函数中的递归没有尽头)。我仍然想知道是否真的有一种方法可以在这里使用通用 IDictionaries 来做我想做的事情。

【问题讨论】:

  • 这样的字典难道不是不可实例化的吗,因为它始终是您定义的开放类型?

标签: c# generics recursion


【解决方案1】:

为了将 Dictionary 或 Dictionary 存储为字典中的值,您需要将字典声明为 Dictionary 类型对象>。

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

然后您需要检查每个值是否是字符串或另一个 Dictionary 或另一个 Dictionary -- C# 在编译时执行 重载解析 ,而不是在运行时!

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

到达叶子时递归将结束,因为 Dictionary 的 HandleDict 重载不会继续递归。

但是,您会注意到,有很多类型检查和强制转换正在进行,而且 Dictionary味道很糟糕——它基本上违背了泛型的目的。

我建议您改为查看访客模式

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 该任务是一个字典到 JSON 的翻译例程,提供了一种从 C# 代码生成任意 JSON 数据的简单方法(我们使用的是 ASP.NET 2.0,并且无法访问 JavascriptSerializer 类)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    • 2022-07-20
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多