C#协方差和继承

Sea*_*ard 7 c# inheritance covariance

我很想知道为什么抽象基类中我的接口的实现不满足子类中的要求.这是一个例子:

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
} 
Run Code Online (Sandbox Code Playgroud)

这是生成的错误:

'ConsoleApplication4.ConcreteManager'未实现接口成员'ConsoleApplication4.IBaseManager <ConsoleApplication4.IConcrete> .Create()'.

'ConsoleApplication4.BaseManager <ConsoleApplication4.Concrete> .Create()'无法实现'ConsoleApplication4.IBaseManager <ConsoleApplication4.IConcrete> .Create()',因为它没有匹配的返回类型'ConsoleApplication4.IConcrete'.

如果我将这些方法添加到ConcreteManager类中,一切都很好,编译器很高兴.

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

public new IEnumerable<IConcrete> SelectAll()
{
    return base.SelectAll();
}
Run Code Online (Sandbox Code Playgroud)

如果简单地返回基类返回的方法就足够了,为什么必须添加方法呢?为什么编译器不能调用基类中的方法?

Eri*_*ert 7

正如John指出的那样,C#语言不支持返回类型协方差.CLR也不是,所以即使语言支持它,我们实际实现该功能的唯一方法就是默默地生成你必须自己添加的代码.

开发人员避免编写这些存根方法的好处实际上并不能证明执行更一般协方差特性的可观成本是合理的,所以我们从未这样做过.


Joh*_*sch 5

看起来你假设返回类型协方差,因为ConcreteManager(作为IConcreteManager)期望两者Create()SelectAll()方法分别具有返回类型IConcreteIEnumerable<IConcrete>基类不提供的方法.

您收到这些错误是因为C#不支持返回类型协方差.