Home > Mobile >  Unable to cast constrained generic interface reference to covariant interface reference
Unable to cast constrained generic interface reference to covariant interface reference

Time:07-24

I'm trying to understand how covariance works with generic type constraints and it seems like the constraints are ignored for no obvious reason.

Consider the following code:

    public interface IContainer<out T> { }

    public interface IContents { }

    public class Food : IContents { }

    public class Foo
    {
        public void Bar<T>() where T : IContents
        {
            IContainer<IContents> x = null;
            IContainer<T> y = null;
            IContainer<Food> z = null;
            x = y; // Cannot convert source type 'IContainer<T>' to target type 'IContainer<IContents>'
            x = z; // Valid
        }
    }

Why does compiler produce 'Cannot convert' error on x = y and produce no error on x = z?

CodePudding user response:

C# does not support variance for value types - from variant generic interfaces doc:

ref, in, and out parameters in C# cannot be variant. Value types also do not support variance.

I.e. next will not work:

public struct MyStruct : IContents
{
}

var structContainer = (IContainer<MyStruct>)null;
IContainer<IContents> x = structContainer;

Since T is not constrained neither to class not to struct it can be either reference type or value type, so in general case IContainer<T> is not assignable to IContainer<IContents>.

Add class constraint to the Bar method:

public class Foo
{
    public void Bar<T>() where T : class, IContents
    {
        IContainer<IContents> x = null;
        IContainer<T> y = null;
        IContainer<Food> z = null;
        x = y; // Now Valid
        x = z; // Valid
    }
}
  • Related