[Edit: My apologies ... the original question wording was ambiguous and I was not getting the responses I am looking for]
For any class X that inherits from class Y, new List<X>() is IEnumerable<Y>
is true. However, this doesn't hold for structs: new List<int>() is IEnumerable<ValueType>
is false. My question is: Why?
Here is a sample program:
class Program
{
class Y { }
class X : Y { }
struct Z { }
static void Main(string[] args)
{
Test(new List<X>());
Test(new List<string>());
Test(new List<Z>());
Test(new List<int>());
Test("blah");
Test(1);
Console.ReadLine();
}
static void Test(object o)
{
if (o is IEnumerable<Y>)
{
Console.WriteLine(o + " is a list of Ys");
}
else if (o is IEnumerable<ValueType>)
{
Console.WriteLine(o + " is a list of ValueTypes");
}
else if (o is IEnumerable<object>)
{
Console.WriteLine(o + " is a list of objects");
}
else if (o is System.Collections.IEnumerable)
{
Console.WriteLine(o + " is most likely a list of ValueTypes or a string");
}
else
{
Console.WriteLine(o + " is not a list");
}
}
}
Output:
System.Collections.Generic.List`1[ConsoleApplication1.Program+X] is a list of Ys
System.Collections.Generic.List`1[System.String] is a list of objects
System.Collections.Generic.List`1[ConsoleApplication1.Program+Z] is most likely a list of ValueTypes or a string
System.Collections.Generic.List`1[System.Int32] is most likely a list of ValueTypes or a string
blah is most likely a list of ValueTypes or a string
1 is not a list
So why is new List<int>
not a IEnumerable<ValueType>
?
Covariance works only for reference types, not for value types. So a List<string>
is assignable to an IEnumerable<object>
because string
is a reference type, but a List<int>
is not assignable to an IEnumerable<ValueType>
. See section 13.1.3.2 of the C# language specifications for details
The type of iArr
(and subsequently iArr[i]
) is known; the compiler can tell you that your expressions will always return a given value because it knows the answer at compile time. There is nothing dynamic going on here.
What are you actually trying to accomplish here? Why would you test if an int
derives from ValueType
? Of course it does; it's an int
! This would possibly make sense were generics involved (though you would likely just use a constraint), but not here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With