Reputation: 19544
In a part of my C# code, I have used the following code to check if an object passed in is a single value or implements IEnumerable<T>
(T
being string, double, int, etc - Never a complex object or class) :
Type type = paramValue.GetType();
if (type != typeof(string) && typeof(System.Collections.IEnumerable).IsAssignableFrom(type))
{
var underlyingType = ((System.Collections.IEnumerable)paramValue).GetType().GetGenericArguments()[0];
}
And it has worked very well in all instances up until today when I passed in an int[]
as I discovered to be an issue here.
So, what would the best way to get the underlying type of an IEnumerable
that also accounts for value types be?
Thanks!!
Upvotes: 2
Views: 1277
Reputation: 460098
You want to know the type and if it's an IEnumerable<T>
(!= string
) you want the T
? For arrays you can use Type.GetElementType
:
public static Type GetUnderlyingType(object paramValue)
{
Type type = paramValue.GetType();
var stringType = typeof(string);
if (type == stringType)
return stringType;
else if (type.IsArray)
type = type.GetElementType();
else if (typeof(System.Collections.IEnumerable).IsAssignableFrom(type))
{
var genericArguments = ((System.Collections.IEnumerable) paramValue).GetType().GetGenericArguments();
if(genericArguments.Length > 0)
type = genericArguments[0];
}
return type;
}
Upvotes: 2
Reputation: 169200
As @Servy says, a non-generic IEnumerable
sequence may contain elements of several different types.
If you only care about the first item in the sequence and assume that all other items are the same type, you could try something like this:
int[] paramValue = new int[] { 1, 2, 3 };
Type type = paramValue.GetType();
Type underlyingType;
if (type != typeof(string))
{
System.Collections.IEnumerable e = paramValue as System.Collections.IEnumerable;
if(e != null)
{
Type eType = e.GetType();
if(eType.IsGenericType)
{
underlyingType = eType.GetType().GetGenericArguments()[0];
}
else
{
foreach(var item in e)
{
underlyingType = item.GetType();
break;
}
}
}
}
Note that, as an example, underlyingType
will be int
for the following paramValue
though:
object[] paramValue = new object[] { 1, "a", "c" };
Upvotes: 0
Reputation: 203817
An IEnumerable
doesn't have an underlying type, at least, not other than object
. You know that each item in the sequence is an object
, but you don't know any more than that. If you want to work with sequences of items where all of those items are of the same type (where that type isn't object
then you need to work with IEnumerable<T>
, not IEnumerable
.
As it is, any given IEnumerable
given to you might have a string and an int and a custom object, all in the same sequence, so there is no common type there other than object
.
Upvotes: -1