[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 anIEnumerable<object>becausestringis a reference type, but aList<int>is not assignable to anIEnumerable<ValueType>. See section 13.1.3.2 of the C# language specifications for details