C # covariance and inheritance

I am curious to know why implementing my interface in an abstract base class does not satisfy the requirements in subclasses. Here is 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 a generated error:

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

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

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

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

If you simply return that the methods from returning the base class are sufficient, why do you need to add methods? Why can't the compiler call methods in the base class?

+6
source share
3 answers

It looks like you are assuming a covariance of the return type, since ConcreteManager (like IConcreteManager ) expects both the Create() and SelectAll() methods with the return types IConcrete and IEnumerable<IConcrete> respectively, that the base class does not provide.

You get these errors because C # does not support return type covariance.

+5
source

As John points out, C # does not support return type covariance. It is also not a CLR, so even if the language supported it, the only way we could implement this function would be to automatically generate exactly the code that you should have added.

The small advantage provided to developers to avoid the need to write these stub methods does not really justify the significant cost of performing the more general covariance function, so we never did.

+7
source

When you implement an interface / abstract class, you must use the same signature. Look here

Do not let generics throw you away, this is no different than if there were no generics.

+1
source

Source: https://habr.com/ru/post/890104/


All Articles