为什么List而不是IEnumerable< ValueType>
本文关键字:IEnumerable ValueType int 为什么 List | 更新日期: 2023-09-27 18:14:38
[编辑:抱歉…]原来的问题措辞含糊不清,我没有得到我正在寻找的回答]
对于任何继承自类Y的类X, new List<X>() is IEnumerable<Y>
为真。然而,这对结构体不成立:new List<int>() is IEnumerable<ValueType>
为假。我的问题是:为什么?
下面是一个示例程序:
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");
}
}
}
输出:System.Collections.Generic.List ' 1 [ConsoleApplication1。Program+X]是Ys的列表
System.Collections.Generic.List ' 1(系统。是一个对象列表
System.Collections.Generic.List ' 1 [ConsoleApplication1。Program+Z]很可能是一个ValueTypes列表或字符串
System.Collections.Generic.List ' 1(系统。Int32]很可能是一个ValueTypes列表或字符串
blah很可能是一个ValueTypes列表或字符串
1不是一个列表
为什么new List<int>
不是IEnumerable<ValueType>
?
协方差只对引用类型有效,对值类型无效。因为string
是引用类型,所以List<string>
可以赋值给IEnumerable<object>
,但是List<int>
不能赋值给IEnumerable<ValueType>
。
iArr
(以及随后的iArr[i]
)的类型已知;编译器可以告诉您,您的表达式将始终返回给定值,因为在编译时知道答案。这里没有任何动态变化。
你到底想要完成什么?为什么要测试int
是否来自ValueType
?当然有;这是int
!如果涉及到泛型,这可能是有意义的(尽管您可能只使用约束),但在这里不是这样。
在您的评论中,看起来您希望List<x>
派生自List<y>
,如果x派生自y,因此您期望某些检查为真。这是List<T>
的无效假设。
如果类型x
与类型y
相关,那么不能在不查看类型本身的情况下谈论RandomGeneric<x>
和RandomGeneric<y>
之间的关系。
在您的特殊情况下,List<x>
和List<y>
始终是兄弟类型(来自共同的父类,但彼此之间没有关系)。IEnumerable<x>
和IEnumerable<y>
也一样。
这个问题没有意义,因为arr中有值类型,因为它是一个整型数组。在编译时不知道元素类型的唯一情况是,如果您有一个对象集合。在这种情况下,每个元素都可以作为对象转换为不同的类型,因此您必须检查每个元素。
。
IEnumerable arse = SomeMethodThatReturnsIEnumerable();
bool areAllValueTypes = arse.<OfTypeobject>().All(x => x is ValueType);
这取决于你的意思。
var lst = new List<Object>();
lst.Add(1);
lst.Add(3);
这是一个碰巧只包含ValueTypes的对象集合。它应该返回真还是假?如果它应该返回false,使用this:
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,使用this:
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;
}
如果传入一个多维数组或构造类型,那么start可能会变得有点复杂。这些都在课上的某个地方