Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I wonder why IEnumerable<int> can't be assigned to a IEnumerable<object>. After all IEnumerable is one of the few interfaces that supports covariance...

  • The subtype relation and covariance stuff works with reference types
  • int seems to be a proper subtype of object

The combination of both features doesn't work however...

class A
{
}

class B : A
{
}

class Program
{
    static void Main(string[] args)
    {
        bool b;
        b = typeof(IEnumerable<A>).IsAssignableFrom(typeof(List<B>));
        Console.WriteLine("ienumerable of ref types is covariant: " + b); //true

        b = typeof(IEnumerable<object>).IsAssignableFrom(typeof(List<int>));
        Console.WriteLine("ienumerable of value tpyes is covariant: " + b); //false

        b = typeof(object).IsAssignableFrom(typeof(int));
        Console.WriteLine("int is a subtype of object: " + b); //true
    }
}

thanks for your help! sebastian

like image 720
Sebastian Gregor Avatar asked Mar 24 '11 01:03

Sebastian Gregor


People also ask

Bahasa C digunakan untuk apa?

Meskipun C dibuat untuk memprogram sistem dan jaringan komputer namun bahasa ini juga sering digunakan dalam mengembangkan software aplikasi. C juga banyak dipakai oleh berbagai jenis platform sistem operasi dan arsitektur komputer, bahkan terdapat beberepa compiler yang sangat populer telah tersedia.

C dalam Latin berapa?

C adalah huruf ketiga dalam alfabet Latin. Dalam bahasa Indonesia, huruf ini disebut ce (dibaca [tʃe]).

Bahasa C dibuat pertama kali oleh siapa dan tahun berapa?

Bahasa pemrograman C ini dikembangkan antara tahun 1969 – 1972 oleh Dennis Ritchie. Yang kemudian dipakai untuk menulis ulang sistem operasi UNIX. Selain untuk mengembangkan UNIX, bahasa C juga dirilis sebagai bahasa pemrograman umum.


3 Answers

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.

like image 76
Ben Voigt Avatar answered Oct 13 '22 17:10

Ben Voigt


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.

like image 27
Andrew Cooper Avatar answered Oct 13 '22 17:10

Andrew Cooper


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.

like image 25
LukeH Avatar answered Oct 13 '22 19:10

LukeH