Search code examples
c#.net-coreobject-oriented-analysis

Assign generic type class implementing interface to generic type being interface


I'm not sure if my question is clear so I will make it clear by the code:

Basically I have a loader interface, with a generic type being an interface. Here, both Cat and Dog implements IAnimal.

private readonly IAnimalLoader<Cat> _catLoader;
private readonly IAnimalLoader<Dog> _dogLoader;

private IAnimalLoader<IAnimal> animalLoader;

public AnimalService(IAnimalLoader<Cat> catLoader,
                     IAnimalLoader<Dog> dogLoader)
{
    _catLoader = catLoader;
    _dogLoader = dogLoader;
}

Problem is when trying to assign either of the loader to animalLoader:

if (animal == AnimalType.Cat)
{
    animalLoader = _catLoader;
}
else
{
    animalLoader = _dogLoader;
}

C# complains about no implicit conversion from Cat to IAnimal, even though it implements it. No cast seems to fix the issue.

Any idea of what I'm doing wrong?

EDIT: Here is IAnimalLoader for clarification

public interface IAnimalLoader<T> where T : IAnimal
{
    IQueryable<T> GetAllQueryable();
    Task<T> GetAsync(string id);
}

Solution

  • While Cat implements IAnimal, IAnimalLoader<Cat> has no such relationship with IAnimalLoader<IAnimal>, which is what the error message is about.

    Generally, one needs to mark the generic parameter as covariant for the conversion to succeed, the syntax is out T IIRC, otherwise, check the C# language reference on generics' variance.

    Updated (Thanks to the comment below): In your case, even that is not possible since one of the types, Task<T>, is invariant. Only interfaces can be marked as variant, classes cannot be.