Search code examples
c#genericstype-conversion

Cannot convert source type to target type compilation error


I have this simple class:

public class Program
{
    private static void Main(string[] args)
    { 
        ClassB<ClassA> objA = new ClassB<ClassA>();

        ClassB<ITestA<MyDTO>> objB = new ClassB<ClassA>();
    }
}

public class ClassB<T>
{
    //some code
}

public interface ITestA<T>
{
    //some code
}

public class MyDTO
{
    //some code
}

public class ClassA : ITestA<MyDTO>
{
    //some code 
}

This line of code:

ClassB<ITestA<MyDTO>> objB = new ClassB<ClassA>();

is giving a compilation error:

Cannot implicitly convert type 'ClassB<ClassA>' to 'ClassB<ITestA<MyDTO>> 

Since ClassA implements ITestA, I don't know why this would give a compilation error. Please help me understand what I am doing wrong.

Thanks, Esen


Solution

  • It's due to a rather complex feature of generics called variance.

    Classes are invariant, which means that if you declare ClassB<T>, then when creating an instance:

    ClassB<T1> obj = new ClassB<T2>
    

    Then T1 has to be exactly the same class as T2.

    You can use interfaces to get around this, eg change your code to the following and it'll compile:

    ...
    public class Program
    {
        private static void Main(string[] args)
        {
            ClassB<ClassA> objA = new ClassB<ClassA>();
    
            IClassB<ITestA<MyDTO>> objB = new ClassB<ClassA>();
    
        }
    }
    
    
    public interface IClassB<out T>  // <- note the out before T
    {
        //some code here
    }
    public class ClassB<T> : IClassB<T>
    {
        //some code here
    }
    ...
    

    In this case, IClassB is declared as covariant, which means that it can handle being given a derived class of T, rather than needing T itself. There are risks around using covariance (and contravariance) though, which is why generic classes are invariant by default.