我正在尝试编写一个递归 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]);
}
}
我还尝试了 HandleDict(IDictionary) 的变体,其中 T : IDictionary
但这也不太有效。我知道我想要做的事情可以通过自定义类作为参数而不是字典来实现,并且我的尝试在概念上是有缺陷的(通用函数中的递归没有尽头)。我仍然想知道是否真的有一种方法可以仅使用通用 IDictionaries 来完成我想要的操作。
I am trying to write a recursive C# function that will operate on generic dictionaries of the form IDictionary<string, T>
where T
is either another IDictionary<string, T>
or a string.
My first failed attempt looked something like this:
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]);
}
}
I also tried variants of HandleDict<T>(IDictionary<string, T>) where T : IDictionary<string, T>
but that also doesn't quite work. I know that what I want to do could be achieved through a custom class as the parameter instead of dictionaries, and that my attempts are conceptually flawed (there's no end to the recursion in the generic function). I would still like to know if there is actually a way to do what I want here using just generic IDictionaries.
发布评论
评论(2)
为了存储字典<字符串,字符串>或或字典作为字典中的值,您需要将字典声明为 Dictionaryobject> 类型。
然后,您需要检查每个值是否是字符串或另一个 Dictionary或另一个字典 -- C# 在编译时执行重载解析,而不是在运行时!
当到达叶子时,递归将结束,因为 Dictionary 的 HandleDict 重载会导致递归失败。不继续递归。
但是,正如您将注意到的,正在进行大量类型检查和转换,并且 Dictionary 会进行很多类型检查和转换。 闻起来很难闻——它本质上违背了仿制药的目的。
我建议您查看访问者模式。
In order to store either a Dictionary<string, string> or a Dictionary<string,??> as a value in a dictionary, you'd need to declare the dictionary to be of type Dictionary<string, object>.
Then you'd need to check for each value if it's a string or another Dictionary<string, string> or another Dictionary<string, object> -- C# performs overload resolution at compile-time, not at run-time!
Recursion would end when a leaf is reached, because the HandleDict overload for Dictionary<string, string> does not continue the recursion.
However, as you'll note, there's a lot of type checking and casting going on, and a Dictionary<string, object> smells badly -- it essentially defeats the purpose of generics.
I suggest you have a look at the Visitor Pattern instead.
C# 类型系统不够强大,无法表示您需要在类型系统中执行此操作的“高级”泛型类型。如果您需要一种具有更丰富的泛型类型系统的语言,请考虑 Haskell 或 F#。
可以使用“动态”功能在 C# 4 中执行您想要的操作,但我建议不要这样做。这样做基本上会在运行时再次启动编译器。我不会诉诸运行时类型分析,而是会花一些时间重新审视最初使用字典的决定。我怀疑有更好的数据结构适合您手头的实际任务。描述该任务,我们将看看是否有更好的数据结构。
The C# type system is not powerful enough to represent the sort of "higher" generic types that you need to do this in the type system proper. Consider Haskell or F# if you need a language with a richer generic type system.
It is possible to do what you want in C# 4 using the 'dynamic' feature, but I'd recommend against it. Doing that basically starts up the compiler again at runtime. Rather than resorting to runtime type analysis I'd spend some time revisiting the decision to use dictionaries in the first place. I suspect there are better data structures for your actual task at hand. Describe that task and we'll see if there are better data structures.