检查Type或实例是否实现IEnumerable而不管Type T

Oct*_*oid 28 .net c# reflection inheritance types

我在我当前的项目中做了大量的反思,我正在尝试提供一些帮助方法,以保持一切整洁.

我想提供一对方法来确定类型或实例是否实现IEnumerable- 无论类型如何T.这就是我现在所拥有的:

public static bool IsEnumerable(this Type type)
{
    return (type is IEnumerable);
}

public static bool IsEnumerable(this object obj)
{
    return (obj as IEnumerable != null);
}
Run Code Online (Sandbox Code Playgroud)

当我用它们测试它们时

Debug.WriteLine("Type IEnumerable:   " + typeof(IEnumerable).IsEnumerable());
Debug.WriteLine("Type IEnumerable<>: " + typeof(IEnumerable<string>).IsEnumerable());
Debug.WriteLine("Type List:          " + typeof(List<string>).IsEnumerable());
Debug.WriteLine("Type string:        " + typeof(string).IsEnumerable());
Debug.WriteLine("Type DateTime:      " + typeof(DateTime).IsEnumerable());
Debug.WriteLine("Instance List:      " + new List<string>().IsEnumerable());
Debug.WriteLine("Instance string:    " + "".IsEnumerable());
Debug.WriteLine("Instance DateTime:  " + new DateTime().IsEnumerable());
Run Code Online (Sandbox Code Playgroud)

我得到了这个结果:

Type IEnumerable:   False
Type IEnumerable<>: False
Type List:          False
Type string:        False
Type DateTime:      False
Instance List:      True
Instance string:    True
Instance DateTime:  False
Run Code Online (Sandbox Code Playgroud)

类型方法似乎根本不起作用 - 我原本期望至少true直接System.Collections.IEnumerable匹配.

我知道这string在技​​术上是可以枚举的,尽管有一些警告.理想情况下,在这种情况下,我需要帮助方法来返回false它.我只需要IEnumerable<T>返回具有已定义类型的实例true.

我可能只是错过了一些相当明显的东西 - 有人能指出我正确的方向吗?

dav*_*v_i 45

以下行

return (type is IEnumerable);
Run Code Online (Sandbox Code Playgroud)

被问"如果一个实例Type,typeIEnumerable",这显然是不.

你想要做的是:

return typeof(IEnumerable).IsAssignableFrom(type);
Run Code Online (Sandbox Code Playgroud)

  • 我现在不知道为什么这是公认的答案。无论 T 如何,IEnumerable 与 IEnumerable&lt;T&gt; 都不一样。可以存在仅实现 IEnumerable 的类型。 (3认同)
  • @Octopoid 字符串实现了`IEnumerable&lt;char&gt;`,所以这是真的,因为这就是你所要求的 (2认同)
  • 如果您出于某种原因排除了`string`,而没有看到您的代码或不知道要求,您可能也想排除许多可能的其他人(特别是如果您正在制作一个可以在未来代码中由未知类型使用的库)这点)。我不明白为什么 `string` 与许多其他可能的 `IEnumerable` 不同。如果是这种情况,您最好明确说明您支持的内容,而不是使用“实现`IEnumerable`”作为检查 (2认同)

Wai*_*Lee 10

除此之外Type.IsAssignableFrom(Type),您还可以使用Type.GetInterfaces():

public static bool ImplementsInterface(this Type type, Type interface)
{
    bool implemented = type.GetInterfaces().Contains(interface);
    return implemented;
}
Run Code Online (Sandbox Code Playgroud)

这样,如果您想检查多个接口,您可以轻松修改ImplementsInterface以采用多个接口.


Wou*_*ter 6

要检查某种类型是否实现了 IEnumerable而不管 T需要检查 GenericTypeDefinition。

public static bool IsIEnumerableOfT(this Type type)
{
    return type.GetInterfaces().Any(x => x.IsGenericType
           && x.GetGenericTypeDefinition() == typeof(IEnumerable<>));
}
Run Code Online (Sandbox Code Playgroud)

  • 小修正:在“type”本身就是“typeof(IEnumerable&lt;T&gt;)”的边缘情况下,这会失败,这在某些情况下可能会导致静默失败:https://dotnetfiddle.net/vLFdHW——修复很简单,只需在“.Any”之前抛出一个“.Append(type)”,以便类型本身也被检查:https://dotnetfiddle.net/5wj1KE (2认同)