1

2 つのクラスで、抽象基本クラスD1からD2派生しBます。それらのそれぞれは、で宣言された共通のパブリック インターフェイスを共有しますがB、それぞれが独自の特定のパブリック インターフェイスを持つ場合もあります (たとえば、オブジェクトに対してのみ意味のあるD2has )。D2.Bar()D2

public abstract class B
{
    public int N { get; set; }
    public abstract void Foo();
}

public class D1 : B
{
    public override void Foo()
    {            
    }
}

public class D2 : B
{
    public override void Foo()
    {
    }

    public void Bar()
    {            
    }
}

Bar()コレクションのすべてのオブジェクトで共通の (継承された) メソッドを呼び出さなければならない場合もありますが、D2オブジェクトのみを呼び出したい場合もあるため、派生オブジェクトを 1 つのコレクション (リストなど) に混在させておきます。

        var list = new List<B>();
        list.Add(new D1());
        list.Add(new D2());
        foreach(var b in list)
            if(b is D2)
                (b as D2).Bar();

ここにコードの匂いがします。ダウンキャストは悪い考えです。型チェックに基づいて決定を下すのは悪い考えです。基本クラスに移動すると、オブジェクトBar()でそれを呼び出す意味がありません( containの実装は何ですか? )。インターフェイスと構成も役に立ちません。これは非常に一般的な状況だと思いますが、この場合のベストプラクティスは何ですか? ダウンキャストを回避しながら、派生型に固有のパブリック メソッドの呼び出しを許可するにはどうすればよいですか?D1D1.Bar()

4

2 に答える 2

5

あなたの説明を考えると、実際には「チェックとダウンキャスト」が正確に適切であるように思えます。

D2 オブジェクトのみで Bar() を呼び出したい場合があります。

ちょっと変わった要件ですが、それ要件である場合は、基本クラスで意味をなさない操作の no-op 実装を追加するのではなく、単純な方法で実装するのが合理的だと思います。

しかし、私はそれについて少し違ったやり方をします:

foreach (var d2 in list.OfType<D2>())
{
    d2.Bar();
}

今、それはあなたが意味することを正確に言います:)

于 2013-08-16T13:44:27.580 に答える