No covariance for value type

For a while now I’ve been wondering why C#’s support for covariance does not cover value types, both in normal array covariance and covariance in the generic parameter introduced in C# 4:

   1: void Main()

   2: {

   3:     int i = 0;

   4:     string str = "hello world";


   6:     TestMethod(i);       // legal

   7:     TestMethod(str);     // legal

   8:     TestMethod2(Enumerable.Empty<int>());           // illegal

   9:     TestMethod2(Enumerable.Empty<string>());        // legal


  11:     Console.WriteLine(i is object);                 // true

  12:     Console.WriteLine(new int[0] is object[]);      // false

  13:     Console.WriteLine(new string[0] is object[]);   // true

  14:     Console.WriteLine(new uint[0] is int[]);        // false

  15: }


  17: public void TestMethod(object obj)

  18: {

  19:     Console.WriteLine(obj);

  20: }


  22: public void TestMethod2(IEnumerable<object> objs)

  23: {

  24:     Console.WriteLine(objs.Count());

  25: }

Until I stumbled upon this old post by Eric Lippert on the topic of array covariance, which essentially points to a disagreement in the C# and CLI specification on the rule of array covariance:


"if X is assignment compatible with Y then X[] is assignment compatible with Y[]"


"if X is a reference type implicitly convertible to reference type Y then X[] is implicitly convertible to Y[]"

Whilst this doesn’t directly point to the generics case with IEnumerable<out T>, one would expect they are one and the same, otherwise you end up with different rules for int[] and IEnumerable<int> where (new int[0] is IEnumerable<int>) == true.. now that would be weird!


Eric Lippert – Why is covariance of value-typed arrays inconsistent?

Question on StackOverflow – why does my C# array lose type sign information when cast to object?

Enjoy what you’re reading? Subscribe to my newsletter and get more content on AWS and serverless technologies delivered straight to your inbox.

Yan Cui

I’m an AWS Serverless Hero and the author of Production-Ready Serverless. I have run production workload at scale in AWS for nearly 10 years and I have been an architect or principal engineer with a variety of industries ranging from banking, e-commerce, sports streaming to mobile gaming. I currently work as an independent consultant focused on AWS and serverless.

You can contact me via Email, Twitter and LinkedIn.

Hire me.

Check out my new course, Complete Guide to AWS Step Functions.

In this course, we’ll cover everything you need to know to use AWS Step Functions service effectively. Including basic concepts, HTTP and event triggers, activities, design patterns and best practices.

Get Your Copy