2012-04-17 80 views
5

繼承出於某種原因,我爭奪用通用的基類按如下方式實現從一個普通的接口屬性:通用基類從通用接口

public interface IParent<TChild> where TChild : IChild 
{ 
    TChild Child { get; } 
} 

public interface IChild { } 

然後,我有一個基類:

public class ParentBase<TChild> : IParent<TChild> where TChild : IChild 
{ 
    private TChild _child; 
    public ParentBase(TChild child) 
    { 
     this._child = child; 
    } 
    #region IParent<TChild> Members 

    public TChild Child 
    { 
     get { return _child; } 
    } 

    #endregion 
} 

現在我有一個新的父衍生和子對象如下:

public class MyChild : IChild { } 

public class MyParent : ParentBase<MyChild>, IParent<IChild> 
{ 
    public MyParent(MyChild child) 
     : base(child) 
    { 
    } 
} 

餘萬噸至實例,並得到了抽象(接口類型)傳遞給消費者如下:

IParent<IChild> parent = new MyParent(new MyChild()); 

但出於某種原因,我不能正確實現年擄,儘管我對ParentBase中定義的屬性public TChild Child中,編譯器說它沒有實現,即使我嘗試明確實現。 正如你所看到的約束是通過基類的所有道路。

+0

您使用的是什麼版本的C#? – Oded 2012-04-17 10:53:00

+0

我正在使用C#4(.NET 4) – Andre 2012-04-17 10:54:06

回答

4

您從ParentBase<MyChild>IParent<IChild>派生MyParent。沒有爲

IParent<IChild> { IChild Child{get; } } 

沒有實現添加一個明確的實施將使您的原始代碼編譯

public class MyParent : ParentBase<MyChild>, IParent<IChild> 
{ 
    public MyParent(MyChild child) 
     : base(child) 
    { 
    } 

    #region Implementation of IParent<IChild> 

    IChild IParent<IChild>.Child 
    { 
     get { return base.Child; } 
    } 

    #endregion 
} 

如果你還讓IParent協這樣的:

public interface IParent<out TChild> where TChild : IChild 
{ 
    TChild Child { get; } 
} 

,那麼你現在可以這樣做

IParent<IChild> parent = new MyParent(new MyChild()); 

ParentBase<MyChild> parent2 = new MyParent(new MyChild()); 

IParent<IChild> parent3 = parent2; 

並且在由@svick回答指出,與協方差然後你可以通過不從IParent<IChild>派生並去除顯式接口實現簡化。

+0

消費者需要使用IParent 而不是具體類型,所以我需要這樣的一個實例。並且,當他們訪問子資產時,它需要僅僅是IChild – Andre 2012-04-17 11:05:35

+0

您需要明確實現IPofrent .Child – Phil 2012-04-17 11:08:24

+0

但是,如果您將'IParent'協變並且不明確指定'IParent '作爲MyParent的基礎',那麼你將不必實現'IParent .Child','ParentBase'中的實現就足夠了。看到我的答案。 – svick 2012-04-17 11:29:01

0

如果消費者需要使用IChild而不是TChild,那麼您是不是可以擺脫通用接口?

public interface IParent 
{ 
    public IChild Child { get; } 
} 

,然後你的產業工作得很好

public class ParentBase<TChild> : IParent where TChild : IChild 
{ 
    public IChild Child { get { return myChild; } } 
} 

public class MyParent : ParentBase<MyChild> // already implements IParent by the base doing so. 
{ 
} 
3

這正是通用的差異是非常有用的。如果您的標記IParent interafce爲協變:

public interface IParent<out TChild> where TChild : IChild 

MyParent刪除的IParent<IChild>明確的推導:

public class MyParent : ParentBase<MyChild> 

然後MyParent可以看作它實現IParent<IChild>。例如,下面的代碼可以工作:

MyParent parent = new MyParent(new MyChild()); 
IParent<IChild> iParent = parent;