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 でプロパティを定義したにもかかわらず、何らかの理由で TChild を正しく実装できませんpublic TChild Child。明示的に実装しようとしても、コンパイラは実装されていないと言います。ご覧のとおり、制約は基本クラスにまで及びます。

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>

thenMyParentは実装されているかのように扱うことができますIParent<IChild>。たとえば、次のコードは機能します。

MyParent parent = new MyParent(new MyChild());
IParent<IChild> iParent = parent;
于 2012-04-17T11:25:59.643 に答える
0

コンシューマーが TChild ではなく IChild を取得する必要がある場合、ジェネリック インターフェイスを取り除くことはできませんか?

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 に答える