Why is List <int> not IEnumerable <ValueType>?
[Edit: My apologies ... the original wording of the question was ambiguous, and I did not receive the answers I am looking for)
For any class X that inherits from class Y, new List<X>() is IEnumerable<Y>is true. However, this does not apply to structs: new List<int>() is IEnumerable<ValueType>false. My question is why?
Here is an example 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");
}
}
}
Conclusion:
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 strings
System.Collections.Generic.List`1 [System.Int32] is most likely a list of ValueTypes or strings
blah is most likely a ValueTypes list or string
1 is not a list
, new List<int> a IEnumerable<ValueType>?
, .
var lst = new List<Object>();
lst.Add(1);
lst.Add(3);
, ValueTypes. true false? false, :
private bool attemptOne(IEnumerable coll)
{
var s = coll.GetType().GetGenericArguments()[0];
return s.IsValueType;
}
var lstTwo = new List<int>();
lstTwo.Add(1);
lstTwo.Add(3);
Console.WriteLine(attemptOne(lstTwo)); // Returns true
true, :
private bool attemptTwo<T>(IEnumerable<T> coll)
{
return coll.All(c => c.GetType().IsValueType);
}
, .
, ,
bool IsCollectionOfValueTypes(Object argValue)
{
Type t = argValue.GetType();
if(t.IsArray)
{
return t.GetElementType().IsValueType;
}
else
{
if (t.IsGeneric)
{
Types[] gt = t.GetGenericArguments();
return (gt.Length == 1) && gt[0].IsValueType;
}
}
return false;
}
In any case, the beginning can be a little complicated if you pass a multidimensional array or a configured type. All this in the classroom somewhere though.