2011-06-09 96 views
6

我很想知道为什么我的接口在抽象基类中的实现不满足子类中的需求。下面是一个例子:C#协方差和继承

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 
} 

这是正在产生的误差:

'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(); 
} 

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

+0

我期望扩展接口是问题,请尝试删除它。 – 2011-06-09 01:32:41

+0

你不想'公共类ConcreteManager:BaseManager ,IConcereteManager'? – 2011-06-09 02:00:26

回答

5

它看起来像你假定返回类型的协方差,因为ConcreteManager(作为IConcreteManager)预计都Create()SelectAll()方法与返回类型分别IConcreteIEnumerable<IConcrete>,其基类不提供。

您正在收到这些错误,因为C#不支持返回类型协方差。

1

当你实现一个接口/抽象类时,你必须使用相同的签名。 See here

不要让仿制药抛弃你,这与没有仿制药没有什么不同。

7

正如John指出的那样,C#语言不支持返回类型协方差。 CLR也不是,所以即使语言支持它,我们实际上可以实现的唯一方式是实现,但该功能将默默生成您必须添加的代码。

为开发人员提供的避免编写这些存根方法的小好处实际上并不能证明执行更一般的协方差特性的相当大的成本,所以我们从来没有这样做过。

+0

因此,如果说covarience是对返回值进行分配的话,那么它会是准确的吗? – 2011-06-09 16:59:17

+0

@Seattle Leonard:我不明白这个问题。协变性是*映射*保留*关系*的*方向*的特性。在返回类型协方差的情况下,我们有两个关系:分配兼容性和虚拟插槽兼容性。在从类型到返回这些类型的方法之间的映射对于这些关系是“协变”的语言中,如果X与Y分配兼容,则返回X的方法与虚拟时隙兼容方法返回Y. – 2011-06-09 17:31:11

+0

@EricLippert我不会说covariant返回类型是给开发人员带来的一小部分好处。在我最新的项目中,我添加了几百个这样的“不变的修复”。或者我一般做错了什么? – KnorxThieus 2017-02-02 17:24:28