54

How to determine if object is of type IEnumerable <T>?

Code:

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());
        }
    }
}

Output:

NS.1.Program+<GetInts>d__0

If I change GetInts to return IList, everything is OK the output is:

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

And this returns 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>)));
        }
    }
}
Piotr Justyna
  • 4,888
  • 3
  • 25
  • 40
Valentin V
  • 24,971
  • 33
  • 103
  • 152

9 Answers9

111

If you mean the collection, then just as:

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

However, I'm assuming (from the example) that you have a Type:

The object will never be "of" type IEnumerable<int> - but it might implement it; I would expect that:

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

would do. If you don't know the T (int in the above), then check all the implemented interfaces:

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;
}

and call:

Type t = GetEnumerableType(type);

if this is null, it isn't IEnumerable<T> for any T - otherwise check t.

Marcel
  • 1,688
  • 1
  • 14
  • 25
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 25
    Just remember that `System.String` implements `IEnumerable`. – tymtam Sep 19 '12 at 07:42
  • 2
    @Tymek indeed - I do quite a lot of library work that handles primitive, inbuilt types and collections - and it is virtually always necessary to pull out scenarios such as `string` *before* applying generalizations, for exactly those reasons. – Marc Gravell Sep 19 '12 at 08:40
  • 4
    if the type is ICollection, which implements IEnumerable, the if statement doesn't evaluate to true. Is there a way to tell that it is IEnumerable or any of its subclasses? – Thiago Silva Jun 24 '14 at 17:18
  • 1
    There's a bug. The GetEnumerableType function does not work: for example, IEnumerable in input will return null. This is because IEnumerable implements IEnumerable, not IEnumerable<>. Any other suggestion? – sthiers Aug 04 '17 at 13:20
20

Since IEnumerable<T> inherit IEnumerable (non generic) and if you don't need to know when a type is just IEnumerable and not IEnumerable<T> then you can use:

if (typeof(IEnumerable).IsAssignableFrom(srcType))
johnnyRose
  • 7,310
  • 17
  • 40
  • 61
Serge Intern
  • 2,669
  • 3
  • 22
  • 39
14

Same technique as Marc's answer, but 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);
        }
    }
}
Mark Rendle
  • 9,274
  • 1
  • 32
  • 58
7

How to determine if object is of type IEnumerable <T>?

Please feel free to use this fine, ultra small, generic extension method to determine if any object implements IEnumerable interface. It extends the Object type, so you can execute it using any instance of any object you're using.

public static class CollectionTestClass
{
    public static Boolean IsEnumerable<T>(this Object testedObject)
    {
        return (testedObject is IEnumerable<T>);
    }
}
Philipp M
  • 1,877
  • 7
  • 27
  • 38
Piotr Justyna
  • 4,888
  • 3
  • 25
  • 40
4

i is of type NS.1.Program+<GetInts>d__0, which is a subtype of IEnumerable<int>. Thus, you can use either

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

or IsAssignableFrom (like in Marc's answer).

Heinzi
  • 167,459
  • 57
  • 363
  • 519
1

You can use the is keyword.

[TestFixture]
class Program
{
    static IEnumerable<int> GetInts()
    {
        yield return 1;
    }

    [Test]
    static void Maasd()
    {
        var i = GetInts();
        Assert.IsTrue(i is IEnumerable<int>);
    }
}
tster
  • 17,883
  • 5
  • 53
  • 72
0

Try

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

Pham Bien
  • 31
  • 4
0

I believe the best way to solve this should be simple.. You first write code that returns the generic arguments (or argument in your case) of the IEnumerable<T> then write another line to make a comparison of the argument type you desire to compare to the type contained in the IEnumerable<T> object (int, in your case). I have an example that displays two simple functions that handles both tasks.

    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;
    }
0

For anyone searching for this who just wants to know how to return true or false on if an object is or inherits from IEnumerable, I've used Marcs original answer to create this generic method I'm now using.

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;
    }