为什么List 不是IEnumerable ?

[编辑:我的道歉……最初的问题措辞含糊不清,我没有得到我正在寻找的回复]

对于从类Yinheritance的任何类X, new List() is IEnumerable是真的。 但是,这不适用于结构: new List() is IEnumerable是false。 我的问题是:为什么?

这是一个示例程序:

 class Program { class Y { } class X : Y { } struct Z { } static void Main(string[] args) { Test(new List()); Test(new List()); Test(new List()); Test(new List()); Test("blah"); Test(1); Console.ReadLine(); } static void Test(object o) { if (o is IEnumerable) { Console.WriteLine(o + " is a list of Ys"); } else if (o is IEnumerable) { Console.WriteLine(o + " is a list of ValueTypes"); } else if (o is IEnumerable) { 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"); } } } 

输出:

System.Collections.Generic.List`1 [ConsoleApplication1.Program + X]是Y的列表

System.Collections.Generic.List`1 [System.String]是一个对象列表

System.Collections.Generic.List`1 [ConsoleApplication1.Program + Z]很可能是ValueTypes或字符串的列表

System.Collections.Generic.List`1 [System.Int32]很可能是ValueTypes或字符串的列表

blah很可能是ValueTypes或字符串的列表

1不是列表

那么为什么new List不是IEnumerable

协方差仅适用于引用类型,不适用于值类型。 因此, List可分配给IEnumerable因为string是引用类型,但List不能分配给IEnumerable 。 有关详细信息,请参阅C#语言规范的第13.1.3.2节

iArr的类型(以及随后的iArr[i] )是已知的 ; 编译器可以告诉您表达式将始终返回给定值,因为它在编译时知道答案 。 这里没有任何动态。

你究竟想在这里完成什么? 为什么要测试int派生自ValueType ? 当然可以; 这是一个int ! 这可能是有意义的涉及generics(虽然你可能只是使用约束),但不是在这里。

在你的评论中,如果x派生自y,你看起来期望ListList派生,因此你期望某些检查是真的。 这是List无效假设。

如果类型x与类型y则无法查看RandomGenericRandomGeneric之间的关系,而无需查看类型RandomGeneric

在您的特定情况下, ListList始终是兄弟类型(派生自普通父类,但彼此之间没有关系)。 IEnumerableIEnumerable

问题没有意义iArr在其中有值类型,因为它是一个int数组。 在编译时你唯一一次不知道元素的类型是你有一个对象的集合。 在这种情况下,每个元素都可以是一个不同类型的元素,因此你必须检查每个元素。

例如

 IEnumerable arse = SomeMethodThatReturnsIEnumerable(); bool areAllValueTypes = arse.().All(x => x is ValueType); 

这取决于你的意思。

 var lst = new List(); lst.Add(1); lst.Add(3); 

这是一组碰巧只包含ValueTypes的对象。 这应该是真还是假? 如果它应该返回false,请使用:

 private bool attemptOne(IEnumerable coll) { var s = coll.GetType().GetGenericArguments()[0]; return s.IsValueType; } var lstTwo = new List(); lstTwo.Add(1); lstTwo.Add(3); Console.WriteLine(attemptOne(lstTwo)); // Returns true 

如果它应该返回true,请使用:

 private bool attemptTwo(IEnumerable 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; } 

如果传入多维数组或构造类型,那么无论如何,启动可能会变得复杂一些。 尽管如此,这一切都在课堂上。