为什么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> ?

为什么List<int>而不是IEnumerable< ValueType>

协方差只对引用类型有效,对值类型无效。因为string是引用类型,所以List<string>可以赋值给IEnumerable<object>,但是List<int>不能赋值给IEnumerable<ValueType>

参见c#语言规范的13.1.3.2节。

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可能会变得有点复杂。这些都在课上的某个地方