2011-06-09 72 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