51

I am trying to determine if a runtime type is some sort of collection type. What I have below works, but it seems strange that I have to name the types that I believe to be collection types in an array like I have done.

In the code below, the reason for the generic logic is because, in my app, I expect all collections to be generic.

bool IsCollectionType(Type type)
{
    if (!type.GetGenericArguments().Any())
        return false;

    Type genericTypeDefinition = type.GetGenericTypeDefinition();
    var collectionTypes = new[] { typeof(IEnumerable<>), typeof(ICollection<>), typeof(IList<>), typeof(List<>) };
    return collectionTypes.Any(x => x.IsAssignableFrom(genericTypeDefinition));
}

How would I refactor this code to be smarter or simpler?

Byron Sommardahl
  • 12,743
  • 15
  • 74
  • 131
  • One thing to keep in mind is that you usually don't want to consider `string` as a collection of `char`s, even though it implements `IEnumerable`. – svick Jun 02 '12 at 18:01

5 Answers5

96

Really all of these types inherit IEnumerable. You can check only for it:

bool IsEnumerableType(Type type)
{
    return (type.GetInterface(nameof(IEnumerable)) != null);
}

or if you really need to check for ICollection:

bool IsCollectionType(Type type)
{
    return (type.GetInterface(nameof(ICollection)) != null);
}

Look at "Syntax" part:

If you need to exclude strings (which are essentially an IEnumerable<char>), use the following function:

bool IsEnumerableType(Type type)
{
    return (type.Name != nameof(String) 
        && type.GetInterface(nameof(IEnumerable)) != null);
}
airsouth
  • 43
  • 4
Ruben
  • 2,488
  • 1
  • 18
  • 22
4

You can use this helper method to check if a type implements an open generic interface. In your case you can use DoesTypeSupportInterface(type, typeof(Collection<>))

public static bool DoesTypeSupportInterface(Type type,Type inter)
{
    if(inter.IsAssignableFrom(type))
        return true;
    if(type.GetInterfaces().Any(i=>i. IsGenericType && i.GetGenericTypeDefinition()==inter))
        return true;
    return false;
}

Or you can simply check for the non generic IEnumerable. All collection interfaces inherit from it. But I wouldn't call any type that implements IEnumerable a collection.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
  • Or use the solution [found here](http://stackoverflow.com/a/1075059/122781) which works for generic types in addition to generic interfaces. – HappyNomad Sep 21 '13 at 23:50
1

You can use linq, search for an interface name like

yourobject.GetType().GetInterfaces().Where(s => s.Name == "IEnumerable")

If this has values is a instance of IEnumerable.

Jones
  • 1,480
  • 19
  • 34
salvador
  • 19
  • 1
1

This solution will take care of ICollection and ICollection<T>.

    static bool IsCollectionType(Type type)
    {
        return type.GetInterfaces().Any(s => s.Namespace == "System.Collections.Generic" && (s.Name == "ICollection" || s.Name.StartsWith("ICollection`")));
    }
daniel.gindi
  • 3,457
  • 1
  • 30
  • 36
0

This work for me.

private static bool IsCollectionType(Type type)
{
    return type.GetInterfaces().Any(s => s.Namespace == "System.Collections.Generic" && (s.Name == "IEnumerable" || s.Name.StartsWith("IEnumerable`")));
}
Henry Ecker
  • 34,399
  • 18
  • 41
  • 57