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
}

现在我有一个新的 Parent Derivative 和 Child 对象,如下所示:

public class MyChild : IChild { }

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

我想实例化它并让抽象(接口类型)传递给消费者,如下所示:

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

但是由于某种原因,我无法正确实现 TChild,即使我已经public TChild Child在 ParentBase 上定义了该属性,编译器仍说它没有实现,即使我尝试显式实现。如您所见,约束一直到基类。

4

3 回答 3

4

ParentBase<MyChild>您正在从和派生 MyParent IParent<IChild>。没有实现

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>和删除显式接口实现来简化。

于 2012-04-17T11:00:03.560 回答
3

这正是通用方差有用的地方。如果您将界面标记IParent为协变:

public interface IParent<out TChild> where TChild : IChild

并删除了IParent<IChild>from的显式推导MyParent

public class MyParent : ParentBase<MyChild>

那么MyParent就可以当作执行了IParent<IChild>。因此,例如,以下代码将起作用:

MyParent parent = new MyParent(new MyChild());
IParent<IChild> iParent = parent;
于 2012-04-17T11:25:59.643 回答
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.
{
}
于 2012-04-17T11:14:13.890 回答