Khaldin K.S.
Khaldin K.S.

Reputation: 23

Unable to cast constrained generic interface reference to covariant interface reference

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?

Upvotes: 2

Views: 54

Answers (1)

Guru Stron
Guru Stron

Reputation: 141990

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

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

i.e. the following 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
    }
}

Upvotes: 1

Related Questions