Why is List not IEnumerable?

后端 未结 6 858
北海茫月
北海茫月 2021-01-05 02:01

[Edit: My apologies ... the original question wording was ambiguous and I was not getting the responses I am looking for]

For any class X that inherits from class Y,

相关标签:
6条回答
  • 2021-01-05 02:21

    Covariance works only for reference types, not for value types. So a List<string> is assignable to an IEnumerable<object> because string is a reference type, but a List<int> is not assignable to an IEnumerable<ValueType>. See section 13.1.3.2 of the C# language specifications for details

    0 讨论(0)
  • 2021-01-05 02:28

    It depends what you mean.

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

    This is a collection of objects which happens to only contain ValueTypes. Should this return true or false? If it should return false, use 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
    

    If it should return true, use this:

    private bool attemptTwo<T>(IEnumerable<T> coll)
    {
        return coll.All(c => c.GetType().IsValueType);
    }
    

    Note that the second way will take a long time for very large collections.

    0 讨论(0)
  • 2021-01-05 02:36

    I think I can see what you are getting at

    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;
    }
    

    A start anyway might get a bit more complicated if you pass in a multidimensional array or a contructed type. It's all in the class somewhere though.

    0 讨论(0)
  • 2021-01-05 02:38

    The type of iArr (and subsequently iArr[i]) is known; the compiler can tell you that your expressions will always return a given value because it knows the answer at compile time. There is nothing dynamic going on here.

    What are you actually trying to accomplish here? Why would you test if an int derives from ValueType? Of course it does; it's an int! This would possibly make sense were generics involved (though you would likely just use a constraint), but not here.

    0 讨论(0)
  • 2021-01-05 02:40

    The question does not make sense iArr has value type in it because it is an array of ints. The only time you are going to not know what the type an element is at compile time is if you have a collection of object. Under that circumstance every element could be a different type cast as an object so you would have to check every element.

    e.g.

    IEnumerable arse = SomeMethodThatReturnsIEnumerable();    
    bool areAllValueTypes = arse.<OfTypeobject>().All(x => x is ValueType);
    
    0 讨论(0)
  • 2021-01-05 02:42

    In your comments it looks like you expect List<x> deriving from List<y> if x derived from y and hence you expect true for some of the checks. This is invalid assumption for List<T>.

    If type x relates to type y you can't say anything about relation between RandomGeneric<x> and RandomGeneric<y> without looking at the types themselvs.

    In your particular case List<x> and List<y> are always sibling types (derive from common parent, but have no relation between each other). The same goes for IEnumerable<x> and IEnumerable<y>.

    0 讨论(0)
提交回复
热议问题