确定类型是否为字典。

56

如何确定Type是否为Dictionary<,>

目前我唯一确定的方法是事先知道类型参数。

例如:

var dict = new Dictionary<string, object>();
var isDict = dict.GetType() == typeof(Dictionary<string, object>; // This Works
var isDict = dict.GetType() == typeof(Dictionary<,>; // This does not work

但字典不一定会是 <string, object>,那么我该如何检查它是否为字典而又不知道参数以及不必检查名称(因为我们也有其他包含单词 Dictionary 的类)?


7
Dictionary<,>对象实现了IDictionary接口,因此可能是typeof(IDictionary) - Ash Burlaczenko
可能会有原始类型吗?我对C#不是很熟悉,但每个类不都是System.Object的后代吗? - sschrass
4个回答

115
Type t = dict.GetType();
bool isDict = t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dictionary<,>);

您可以获取键和值的类型:

Type keyType = t.GetGenericArguments()[0];
Type valueType = t.GetGenericArguments()[1];

GetGenericTypeDefinitions 抛出了一个类型为“System.InvalidOperationException”的异常。这一定是因为我正在针对非泛型类型进行测试。我真是太蠢了! - Theun Arbeider
@TheunArbeider - 只有在类型不是泛型时才会发生这种情况,您是否包含了 IsGenericType 条件? - Lee
哦,忘记了isgenerictype :) - Theun Arbeider
为什么这个答案没有被归类到重复问题中?我认为它应该被归类。 - Almo
这非常有帮助,但缺少我需要的最后一部分 - 将未知对象转换为 Dictionary<,>。可以通过使用 dynamic genericType = Convert.ChangeType(obj, t); 来实现。 - NightOwl888

12
您可以使用IsAssignableFrom 来检查类型是否实现了IDictionary
var dict = new Dictionary<string, object>();

var isDict = typeof(IDictionary).IsAssignableFrom(dict.GetType());

Console.WriteLine(isDict); //prints true

这段代码将会对所有未实现 IDictionary 接口的类型输出 false。


7
这有一个非常简单的方法可以做到这一点,而且你已经非常接近成功了。
尝试这个:
var dict = new Dictionary<string, object>();
var isDict = (dict.GetType().GetGenericTypeDefinition() == typeof(Dictionary<,>))

不行,你需要先检查类型是否为泛型类型。否则,你可能会得到“InvalidOperationException: 'This operation is only valid on generic types.'”的异常。 - Alex Klaus

1
如何?
Dictionary<string, object> d = new Dictionary<string, object>();
Dictionary<int, string> d2 = new Dictionary<int, string>();
List<string> d3 = new List<string>();

Console.WriteLine(d is System.Collections.IDictionary);
Console.WriteLine(d2 is System.Collections.IDictionary);
Console.WriteLine(d3 is System.Collections.IDictionary);

作为所有通用字典类型的继承者,它们都继承自IDictionary接口,因此您可以仅仅检查这一点。

这看起来很好,但不起作用:“使用通用类型'System.Collections.Generic.IDictionary<TKey,TValue>'需要2个类型参数”。 - Boris Zinchenko
@BorisZinchenko刚刚将这段代码复制粘贴到测试中运行了一下,没有出现任何错误。而你提到的错误信息似乎是在字典定义中缺少了一个类型。例如Dictionary<string>Dictionary<string, object>之间的区别。 - Igarioshka
您可以在此处查看您的代码和错误:https://dotnetfiddle.net/JJpHIi - Boris Zinchenko
1
出现需要泛型参数的错误是因为编译器认为您想使用没有类型的 System.Collections.Generic.IDictionary<TKey, TValue>。在我的示例中,我使用了非泛型接口 System.Collections.IDictionary。此外,如果您查看泛型 Dictionary 类的定义,它确实按照文档实现了非泛型 IDictionary 接口。 - Igarioshka
非常感谢您的澄清。使用显式的命名空间解析,代码已经编译正确。我已编辑了您的答案,以便其他人不再像我一样感到困惑。 - Boris Zinchenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接