Stephen Cossgrove
Stephen Cossgrove

Reputation: 507

Reflection, Casting List<Int32> to IEnumerable<object>

I have a class that i need to reflect through an object properties and check values and other things. Everything seems to be working exception when i have a list and try to convert the item to an IEnumerable.

if (propType.GetInterfaces().Contains(typeof(IEnumerable)))
{
    var value = prop.GetValue(source);
    Type underlyingType = propType.GetGenericArguments()[0];

    var enumerable = value as IEnumerable<object>;
    if(enumerable == null)
    {
        // problem here......
    }

    // Check the items in the list
}

The propType comes back as:

FullName = "System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"

The underlyingType comes back as:

System.Int32

This works when it is a list of custom classes, it just seems to be breaking when it is a value type.

Can anyone help here?

Upvotes: 3

Views: 304

Answers (1)

MarcinJuraszek
MarcinJuraszek

Reputation: 125610

The fact that int is a value type makes the difference here. According to C# spec there must be a reference or identity conversion between generic types to make types variant-convertible:

A type T<A1, …, An> is variance-convertible to a type T<B1, …, Bn> if T is either an interface or a delegate type declared with the variant type parameters T<X1, …, Xn>, and for each variant type parameter Xi one of the following holds:

  • Xi is covariant and an implicit reference or identity conversion exists from Ai to Bi
  • Xi is contravariant and an implicit reference or identity conversion exists from Bi to Ai
  • Xi is invariant and an identity conversion exists from Ai to Bi

IEnumerable<T> is covariant, so the line I marked is important. Ai in your case is int and Bi is int. There is no reference conversion from int to object, because int is not a reference type. There is also no identity conversion between these two, because they are not the same.

I don't know the entire context of your question, but you can use non-generic IEnumerable instead of IEnumerable<object>. They are pretty much the same. However, you might be facing an XY problem here, so it's hard to help you without knowing more about your case.

Upvotes: 5

Related Questions