Note, this question is a bit subtle so read it carefully: I'm not just trying to find out whether some artibitrary type implements IEnumerable:
Here's a function I've written with an initial implementation:
// is "toType" some sort of sequence that would be satisfied
// by an array of type T? If so, what is the type of T?
// e.g.
// getArrayType(typeof(string[]) == typeof(string)
// getArrayType(typeof(IEnumerable<int>)) == typeof(int)
// getArrayType(typeof(List<string>)) == null // NOTE - Array<string> does not convert to List<string>
// etc.
private static Type getArrayType(Type toType)
{
if (toType.IsArray)
{
if (toType.GetArrayRank() != 1)
return null;
return toType.GetElementType();
}
// Look for IEnumerable<T>, and if so, return the type of T
if (toType.IsGenericType && toType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
return toType.GetGenericArguments()[0];
return null;
}
Can it be better and handle more cases? e.g. currently
getType(typeof(ICollection<string>)) == null
but string[] is convertible to ICollection
Note also, I don't know in advance what the "element" type is.
The context is: I'm writing a reflection binding to a scripting language and I want it to "just work" if you pass an object[] to some method that expects IEnumerable (it would convert each of the elements of the input array to a string, in this case).
So to clarify, say I have some method signature:
void WriteCSV(ICollection<string> fields);
and my script interpreter has an array of objects that all happen to be Convert-ible to string:
object[] fields = new object[] { "one", 2, "three" };
Then my script interpreter needs to figure out that what's really needed in this case is an array of strings.
Whereas I want my script interpreter to give up on, say:
void WriteCSV(IRecord record);
even though IRecord might even implement some IEnumerable:
interface IRecord : IEnumerable<string>
{
void OtherMethods();
}
There's no way I can construct an IRecord from an array of anything.
So just finding out what IEnumerables a type implements isn't what I need. I said it was subtle didn't I?