为什么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,你看起来期望List
从List
派生,因此你期望某些检查是真的。 这是List
无效假设。
如果类型x
与类型y
, 则无法查看RandomGeneric
和RandomGeneric
之间的关系,而无需查看类型RandomGeneric
。
在您的特定情况下, List
和List
始终是兄弟类型(派生自普通父类,但彼此之间没有关系)。 IEnumerable
和IEnumerable
。
问题没有意义iArr在其中有值类型,因为它是一个int数组。 在编译时你唯一一次不知道元素的类型是你有一个对象的集合。 在这种情况下,每个元素都可以是一个不同类型的元素,因此你必须检查每个元素。
例如
IEnumerable arse = SomeMethodThatReturnsIEnumerable(); bool areAllValueTypes = arse.().All(x => x is ValueType);
这取决于你的意思。
var lst = new List
这是一组碰巧只包含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; }
如果传入多维数组或构造类型,那么无论如何,启动可能会变得复杂一些。 尽管如此,这一切都在课堂上。