2012-04-17 57 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;