'How to determine if a type is a type of collection?
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?
Solution 1:[1]
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);
}
Solution 2:[2]
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.
Solution 3:[3]
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
.
Solution 4:[4]
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`")));
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | airsouth |
Solution 2 | CodesInChaos |
Solution 3 | Jones |
Solution 4 | daniel.gindi |