#1,147 – Why Generics Don’t Support Covariance

In C#, arrays support covariance, but generics do not.  Generics aren’t covariant in order to avoid the problem that we have with covariant arrays.  With arrays, we get type mismatch exceptions when trying to put something into the array of the wrong type.  The core problem here is that the array looks syntactically like an array of the base type, but is actually an array of the more derived type.

Generics in C# aren’t covariant in order to avoid this same problem.  The language designers decided to support covariance for arrays but not for generics.  The reasons are likely more historical than technical.

            // Array covariance--OK
            Dog[] dogs = new Terrier[5];

            // The problem with array covariance.
            // Compiler allows, but throws ArrayTypeMismatchException
            // at run-time
            dogs[0] = new BorderCollie("Shep");

            // Generic covariance--not allowed (compiler error)
            List<Dog> moreDogs = new List<Terrier>();
Advertisements

About Sean
Software developer in the Twin Cities area, passionate about .NET technologies. Equally passionate about my own personal projects related to family history and preservation of family stories and photos.

6 Responses to #1,147 – Why Generics Don’t Support Covariance

  1. Pingback: Dew Drop – July 28, 2014 (#1823) | Morning Dew

  2. Eric Lippert describes why arrays were made to support covariance here:

    http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx

    He does note how unhappy he was about the decision.

  3. Joseph says:

    Again, generics can be covariant or contravariant. The reason List is not is because the type must go both directions; a generic readonly collection, or a generic IEnumerable or Action or Func can all be variant.

    • Sean says:

      Generic interfaces and delegates support variance, but generic types do not.

      • Joseph says:

        Ah; I think it’s clearer to say generic classes and structs are the only generic types which are invariant. Types (I believe) can be interface types, delegate types, enums, etc.

  4. Steve says:

    The reason throwing ArrayTypeMismatchException at run-time is because the actual type of dogs[0] is Terrier.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: