先前接受的答案很好,但这是错误的。值得庆幸的是,该错误很小。
IEnumerable如果您真的想了解接口的通用版本,那么仅进行检查是不够的。有很多只实现非通用接口的类。一分钟后,我会给出答案。不过,首先,我想指出,所接受的答案过于复杂,因为在给定的情况下,以下代码将实现相同的效果:
if (items[key] is IEnumerable)
这样做的好处甚至更多,因为它分别适用于每个项目(而不适用于它们的公共子类
V)。
现在,寻找正确的解决方案。这有点复杂,因为我们必须采用泛型
IEnumerable1
(即IEnumerable<>`具有一个类型参数的类型)并注入正确的泛型参数:
static bool IsGenericEnumerable(Type t) { var genArgs = t.GetGenericArguments(); if (genArgs.Length == 1 && typeof(IEnumerable<>).MakeGenericType(genArgs).IsAssignableFrom(t)) return true; else return t.baseType != null && IsGenericEnumerable(t.baseType);}您可以轻松测试此代码的正确性:
var xs = new List<string>();var ys = new System.Collections.ArrayList();Console.WriteLine(IsGenericEnumerable(xs.GetType()));Console.WriteLine(IsGenericEnumerable(ys.GetType()));
产量:
TrueFalse
不要太在意使用反射的事实。的确,这确实增加了运行时开销,但使用
is运算符也是如此。
当然,上面的代码受到严格限制,可以扩展为更通用的方法
IsAssignableToGenericType。以下实施方式略有错误1,我仅将其留在 历史上
。 不要使用它
。取而代之的是,James在回答中提供了一个出色而正确的实现。
public static bool IsAssignableToGenericType(Type givenType, Type genericType) { var interfaceTypes = givenType.GetInterfaces(); foreach (var it in interfaceTypes) if (it.IsGenericType) if (it.GetGenericTypeDefinition() == genericType) return true; Type baseType = givenType.baseType; if (baseType == null) return false; return baseType.IsGenericType && baseType.GetGenericTypeDefinition() == genericType || IsAssignableToGenericType(baseType, genericType);}1当与
genericType相同时失败
givenType。由于相同的原因,它对于可为空的类型也会失败,即
IsAssignableToGenericType(typeof(List<int>), typeof(List<>)) == falseIsAssignableToGenericType(typeof(int?), typeof(Nullable<>)) == false
我已经创建了包含一整套测试用例的要点。



