【问题标题】:Determine if collection is of type IEnumerable<T>确定集合是否为 IEnumerable<T> 类型
【发布时间】:2010-12-23 05:33:50
【问题描述】:

如何判断对象是否为IEnumerable类型?

代码:

namespace NS {
    class Program {
        static IEnumerable<int> GetInts() {
            yield return 1;
        }
        static void Main() {
            var i = GetInts();
            var type = i.GetType();
            Console.WriteLine(type.ToString());
        }
    }
}

输出:

NS.1.Program+<GetInts>d__0

如果我将 GetInts 更改为返回 IList,一切正常 输出是:

 System.Collections.Generic.List`1[System.Int32]

这会返回 false:

namespace NS {
    class Program {
        static IEnumerable<int> GetInts() {
            yield return 1;
        }
        static void Main() {
            var i = GetInts();
            var type = i.GetType();
            Console.WriteLine(type.Equals(typeof(IEnumerable<int>)));
        }
    }
}

【问题讨论】:

    标签: c# .net linq collections types


    【解决方案1】:

    如果您指的是集合,那么只需as

    var asEnumerable = i as IEnumerable<int>;
    if(asEnumerable != null) { ... }
    

    但是,我假设(从示例中)您有一个Type

    object 永远不会是“属于”IEnumerable&lt;int&gt; 类型的——但它可能会实现它;我希望:

    if(typeof(IEnumerable<int>).IsAssignableFrom(type)) {...}
    

    会的。如果你不知道T(上面的int),那么检查所有实现的接口:

    static Type GetEnumerableType(Type type) {
        if (type.IsInterface && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
            return type.GetGenericArguments()[0];
        foreach (Type intType in type.GetInterfaces()) {
            if (intType.IsGenericType
                && intType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) {
                return intType.GetGenericArguments()[0];
            }
        }
        return null;
    }
    

    然后调用:

    Type t = GetEnumerableType(type);
    

    如果为空,则任何T 都不是IEnumerable&lt;T&gt; - 否则检查t

    【讨论】:

    • 请记住 System.String 实现了 IEnumerable&lt;char&gt;
    • @Tymek 确实 - 我做了很多处理原始、内置类型和集合的库工作 - 几乎总是需要提取诸如 string 之类的场景 before i> 应用概括,正是出于这些原因。
    • 如果类型是实现 IEnumerable 的 ICollection,则 if 语句不会计算为真。有没有办法判断它是 IEnumerable 还是它的任何子类?
    • 有一个错误。 GetEnumerableType 函数不起作用:例如,输入中的 IEnumerable 将返回 null。这是因为 IEnumerable 实现了 IEnumerable,而不是 IEnumerable。还有其他建议吗?
    【解决方案2】:

    iNS.1.Program+&lt;GetInts&gt;d__0 类型,它是IEnumerable&lt;int&gt;子类型。因此,您可以使用任一

    if (i is IEnumerable<int>) { ... }
    

    IsAssignableFrom(如马克的回答)。

    【讨论】:

      【解决方案3】:

      您可以使用is 关键字。

      [TestFixture]
      class Program
      {
          static IEnumerable<int> GetInts()
          {
              yield return 1;
          }
      
          [Test]
          static void Maasd()
          {
              var i = GetInts();
              Assert.IsTrue(i is IEnumerable<int>);
          }
      }
      

      【讨论】:

        【解决方案4】:

        与 Marc 的回答相同,但 Linqier:

        namespace NS
        {
            class Program
            {
                static IEnumerable<int> GetInts()
                {
                    yield return 1;
                }
        
                static void Main()
                {
                    var i = GetInts();
                    var type = i.GetType();
                    var isEnumerableOfT = type.GetInterfaces()
                        .Any(ti => ti.IsGenericType
                             && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>));
                    Console.WriteLine(isEnumerableOfT);
                }
            }
        }
        

        【讨论】:

          【解决方案5】:

          如何判断对象是否属于类型 IEnumerable ?

          请随意使用这种精细、超小型、通用的扩展方法来确定是否有任何对象实现了 IEnumerable 接口。它扩展了 Object 类型,因此您可以使用您正在使用的任何对象的任何实例来执行它。

          public static class CollectionTestClass
          {
              public static Boolean IsEnumerable<T>(this Object testedObject)
              {
                  return (testedObject is IEnumerable<T>);
              }
          }
          

          【讨论】:

            【解决方案6】:

            由于 IEnumerable 继承 IEnumerable(非泛型),如果您不需要知道类型何时只是 IEnumerable 而不是 IEnumerable,那么您可以使用:

            if (typeof(IEnumerable).IsAssignableFrom(srcType))
            

            【讨论】:

            • string 也是 IEnumerable,上面的检查返回 true 为 string 类型。
            【解决方案7】:

            试试

            type.GetInterface("IEnumerable") != null && type.IsGenericType

            【讨论】:

              【解决方案8】:

              我相信解决这个问题的最好方法应该很简单。你首先编写返回IEnumerable&lt;T&gt; 的通用参数(或你的情况下的参数)的代码,然后编写另一行来比较你的参数类型希望与 IEnumerable&lt;T&gt; 对象(在您的情况下为 int)中包含的类型进行比较。我有一个示例,它显示了处理这两个任务的两个简单函数。

                  public static Type GetEnumerableArgumentType(Type type)
                  {
                      if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
                          return type.GetGenericArguments()[0];
                      else
                          return null;            
                  }        
              
                  public static bool EnumerableContainsArgumentType(Type tEnumerable, Type tGenArg)
                  {
                      return GetEnumerableArgumentType(tEnumerable) == tGenArg;
                  }
              

              【讨论】:

                【解决方案9】:

                对于任何搜索这个只想知道如何返回真或假的人,如果一个对象是或继承自 IEnumerable,我已经使用 Marcs 原始答案来创建我现在正在使用的这个通用方法。

                private static bool ImplementsIEnumerable<T>(T obj)
                    {
                        var type = obj.GetType();
                        if (type.IsInterface && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
                        {
                            return true;
                        }
                        foreach (Type interfaceUsed in type.GetInterfaces())
                        {
                            if (interfaceUsed.IsGenericType
                                && interfaceUsed.GetGenericTypeDefinition() == typeof(IEnumerable<>))
                            {
                                return true;
                            }
                        }
                        return false;
                    }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-06-25
                  • 2017-09-28
                  • 1970-01-01
                  • 2016-02-13
                  • 2010-09-27
                  • 1970-01-01
                  相关资源
                  最近更新 更多