c#4.0: int a real subtype of object? covariance, ienumerable and value types

前端 未结 4 1205
鱼传尺愫
鱼传尺愫 2021-01-02 09:18

I wonder why IEnumerable can\'t be assigned to a IEnumerable. After all IEnumerable is one of the few interfa
相关标签:
4条回答
  • 2021-01-02 09:44

    Every value type in .net has a corresponding ("boxed") object type. Non-boxed value types are effectively outside the object type hierarchy, but the compiler will perform a widening from the value type to the boxed class type. It would be helpful to have a "class" Boxed<T> which would support a widening conversions to and from T, but which would be a class type. Internally, I think that's what the compiler's doing implicitly, but I don't know any way to do it explicitly. For any particular type like "integer", there would be no difficulty defining a class which would behave as a Boxed<Integer> should, but I don't know any way of doing such a thing in generic fashion.

    0 讨论(0)
  • 2021-01-02 09:45

    The simplistic answer is that this is just one of the quirks in the way that variance is implemented in C# and the CLR.

    From "Covariance and Contravariance in Generics":

    Variance applies only to reference types; if you specify a value type for a variant type parameter, that type parameter is invariant for the resulting constructed type.

    0 讨论(0)
  • 2021-01-02 09:49

    The problem is that object is a reference type, not a value type. The only reason you can assign an int to a variable of type object is boxing.

    In order to assign List<int> to IEnumerable<object> you'd have to box each element of the list. You can't do that just by assigning the reference to the list and calling it a different type.

    0 讨论(0)
  • 2021-01-02 09:51

    Value types aren't LSP-subtypes of object until they're boxed.

    Variance doesn't work with value types. At all.


    Demonstration that int is not a proper subtype (subtype in the LSP sense) of object:

    Works:

    object x = new object();
    lock (x) { ... }
    

    Does not work (substitutability violated):

    int y = new int();
    lock (y) { ... }
    

    Returns true:

    object x = new object();
    object a = x;
    object b = x;
    return ReferenceEquals(a, b);
    

    Returns false (substitutability violated):

    int y = new int();
    object a = y;
    object b = y;
    return ReferenceEquals(a, b);
    

    Of course, the topic of the question (interface variance) is a third demonstration.

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