Search code examples
c#genericscovariancecontravariance

C# generics is keyword covariance / contravariance type inferral


Please consider this interface:

public interface IInitialiazableEntity<TRepository> where TRepository : class, IRepository
{
    void Initialize(TRepository repository);
}

This class (snippet):

public class SomeFacade<TRepository> where TRepository : class, IRepository
{
        public void Add<TEntity>(TEntity entity) where TEntity : AbstractEntity
        {
            try
            {
                if (entity is IInitialiazableEntity<TRepository>)
                    (entity as IInitialiazableEntity<TRepository>).Initialize(this.Repository);
            }
            catch (Exception ex)
            {
                this.Logger.Error(ex);
            }
        }
}

And the entity:

public class Student : AbstractEntity, IInitialiazableEntity<IRepository>
{ 
    void Initialize(IRepository repository) { ... }
}

Since the student is only IInitialiazableEntity<IRepository> and the facade will have an actual repository which is more specialized than the basic IRepository (i.e. it will be IMySpecialRepository : IRepository), will the is keyword realize that it can cast the IMySpecialRepository and pass it to the Initialize method of the entity? Or if not, how to do it?


Solution

  • Currently, if you had an instance SomeFacade<IMySpecialRepository> the code will not work.

    You have two options, one is the answer provided by Dan Bryant, the other is to make IInitialiazableEntity<TRepository> contravariant.

    Your interface declaration will become (note the in on the generic type):

    public interface IInitialiazableEntity<in TRepository> where TRepository : class, IRepository
    {
        void Initialize(TRepository repository);
    }
    

    This will allow your is check and cast to work, as IInitialiazableEntity<IRepository> can be cast to IInitialiazableEntity<IMySpecialRepository> when using a contravariant generic.

    See here for more information about Covariance and Contravariance in generics.