Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# covariance and inheritance

I'm curious to know why the implementation of my interface in the abstract base class does not satisfy the the requirements in sub-classes. Here's an example:

public interface IBase { }
public interface IConcrete : IBase { }

public interface IBaseManager<out T>
    where T : IBase
{
    T Create();
    IEnumerable<T> SelectAll();
}

public interface IConcreteManager : IBaseManager<IConcrete> { }

public abstract class Base : IBase { }

public class Concrete1 : Base, IConcrete { }

public abstract class BaseManager<T> : IBaseManager<T> where T : class, IBase
{
    #region IBaseManager<T> Members

    public T Create()
    {
        throw new NotImplementedException();
    }

    public IEnumerable<T> SelectAll()
    {
        throw new NotImplementedException();
    }

    #endregion
}

public class ConcreteManager : BaseManager<Concrete>, IConcereteManager
{
             //error occurs here
} 

This is the error that is being generated:

'ConsoleApplication4.ConcreteManager' does not implement interface member 'ConsoleApplication4.IBaseManager<ConsoleApplication4.IConcrete>.Create()'.

'ConsoleApplication4.BaseManager<ConsoleApplication4.Concrete>.Create()' cannot implement 'ConsoleApplication4.IBaseManager<ConsoleApplication4.IConcrete>.Create()' because it does not have the matching return type of 'ConsoleApplication4.IConcrete'.

If I add these methods to the ConcreteManager class, everything is fine and the compiler is happy.

public new IConcrete Create()
{
    return base.Create();
}

public new IEnumerable<IConcrete> SelectAll()
{
    return base.SelectAll();
}

If simply returning what the methods from the base class return is sufficient, why do the methods have to be added? Why can't the compiler call the methods in the base class?

like image 653
Seattle Leonard Avatar asked Jun 09 '11 01:06

Seattle Leonard


1 Answers

As John points out correctly, the C# language does not support return type covariance. Neither does the CLR, so even if the language supported it, the only way we could actually implement the feature would be to silently generate exactly the code you've had to add yourself.

The small benefit afforded to developers of avoiding having to write those stub methods really does not justify the considerable cost of doing the more general covariance feature, so we've never done it.

like image 125
Eric Lippert Avatar answered Oct 23 '22 14:10

Eric Lippert