Determine if object derives from collection type

前端 未结 11 2071
时光说笑
时光说笑 2021-02-05 04:53

I want to determine if a generic object type (\"T\") method type parameter is a collection type. I would typically be sending T through as a Generic.List but it could be any co

相关标签:
11条回答
  • 2021-02-05 05:33

    You can use Type.GetInterface() with the mangled name.

    private bool IsTAnEnumerable<T>(T x)
    {
        return null != typeof(T).GetInterface("IEnumerable`1");
    }
    
    0 讨论(0)
  • 2021-02-05 05:33

    Personally I tend to use a method that I wrote myself, called TryGetInterfaceGenericParameters, which I posted below. Here is how to use it in your case:

    Example of use

    object currentObj = ...;  // get the object
    Type[] typeArguments;
    if (currentObj.GetType().TryGetInterfaceGenericParameters(typeof(IEnumerable<>), out typeArguments))
    {
        var innerType = typeArguments[0];
        // currentObj implements IEnumerable<innerType>
    }
    else
    {
        // The type does not implement IEnumerable<T> for any T
    }
    

    It is important to note here that you pass in typeof(IEnumerable<>), not typeof(IEnumerable) (which is an entirely different type) and also not typeof(IEnumerable<T>) for any T (if you already know the T, you don’t need this method). Of course this works with any generic interface, e.g. you can use typeof(IDictionary<,>) as well (but not typeof(IDictionary)).

    Method source

    /// <summary>
    ///     Determines whether the current type is or implements the specified generic interface, and determines that
    ///     interface's generic type parameters.</summary>
    /// <param name="type">
    ///     The current type.</param>
    /// <param name="interface">
    ///     A generic type definition for an interface, e.g. typeof(ICollection&lt;&gt;) or typeof(IDictionary&lt;,&gt;).</param>
    /// <param name="typeParameters">
    ///     Will receive an array containing the generic type parameters of the interface.</param>
    /// <returns>
    ///     True if the current type is or implements the specified generic interface.</returns>
    public static bool TryGetInterfaceGenericParameters(this Type type, Type @interface, out Type[] typeParameters)
    {
        typeParameters = null;
    
        if (type.IsGenericType && type.GetGenericTypeDefinition() == @interface)
        {
            typeParameters = type.GetGenericArguments();
            return true;
        }
    
        var implements = type.FindInterfaces((ty, obj) => ty.IsGenericType && ty.GetGenericTypeDefinition() == @interface, null).FirstOrDefault();
        if (implements == null)
            return false;
    
        typeParameters = implements.GetGenericArguments();
        return true;
    }
    
    0 讨论(0)
  • 2021-02-05 05:36

    Also, remember just because you are using generics, don't forget other basic techniques, in this case, like overloading. I suspect the you are planning something like this:

    void SomeFunc<T>(T t)
    {
        if (IsCollectionCase(t))
           DoSomethingForCollections()
        else
           DoSOmethingElse();
    }
    

    This would be far better handled as:

    void SomeFunc(IEnumerable t)
    {
           DoSomethingForCollections()
    }
    void SomeFunc<T>(T t)
    {
           DoSomethingElse()
    }
    
    0 讨论(0)
  • 2021-02-05 05:43

    In order to get the actual type of T at runtime, you can use the typeof(T) expression. From there the normal type comparison operators will do the trick

    bool isEnumerable = typeof(IEnumerable<int>).IsAssignableFrom(typeof(T));
    

    Full Code Sample:

    static bool Foo<T>()
    {
      return typeof(IEnumerable<int>).IsAssignableFrom(typeof(T));
    }
    
    Foo<List<T>>();  // true
    Foo<int>(); // false
    
    0 讨论(0)
  • 2021-02-05 05:44

    If you want to do a check and get true for any list/collection/IEnumerable, but get false for type of string, then

       private static bool IsIEnumerable(Type requestType)
       {
          var isIEnumerable = typeof(IEnumerable).IsAssignableFrom(requestType);
          var notString = !typeof(string).IsAssignableFrom(requestType);
          return isIEnumerable && notString;
       }
    
    0 讨论(0)
  • 2021-02-05 05:46

    I would test IEnumerable instead, since a collection type could implement only IEnumerable, it doesn't have to implement IEnumerable<T>.

    It also depends: what do you mean with collection type? You could have a collection without implementing any of those interfaces.

    0 讨论(0)
提交回复
热议问题