1

C# 4.0 は、オーバーライドのパラメーターで共分散 (「in」キーワードを使用) をサポートしていないようです。そうですか?

もしそうなら、これを行うためのよりエレガントな方法はありますか?

環境

public interface IBaseEvent { /* ... */ }

public interface IDerivedEvent : IBaseEvent { /* ... */ }

public class MoreDerivedEvent : IDerivedEvent { /* ... */ }

を処理する一連のクラスがありMoreDerivedEventます。イベント処理コードの制限により、 のイベント ハンドラーを 1 つしか登録できず、MoreDerivedEventインターフェイスの登録をイベントとして処理するかどうかもわかりません (ガイダンスではクラスを明示的に使用するため、処理されるとは思いません)。 )。したがって、イベントを適切に処理するために、次のようにハンドラーを定義しました。

public class BaseType
{
    protected virtual void Handle(IBaseEvent @event) { /* Do Base Stuff */ }
}

public class DerivedType
{
    protected virtual void Handle(IDerivedEvent @event)
    {
        /* Do Derived Stuff */
        Handle((IBaseEvent)@event);
    }

    protected override sealed void Handle(IBaseEvent @event)
    {
        base.Handle(@event);
    }
}

これは明らかに真の継承を提供しません。この問題を解決できない場合はDerivedType、派生した型をフラット化するだけです。BaseTypeしかし、最初に Stack Overflow コミュニティに投稿することにしました。

4

2 に答える 2

7

まず、パラメーターの型共分散はtypesafe ではありません。パラメータ型の共分散を許可したとします。

class B 
{
    public virtual void Frob(Animal a)
    {
    }
}
class D : B
{
    public override void Frob(Giraffe g)
    {
    }
}
....
B b = new D();
b.Frob(new Tiger());  // Calls D.Frob, which takes a giraffe.

いいえ、共分散はあなたが望むものではありません。安全ではありません。パラメータの型ではなく、戻り値の型で共分散が必要です。反変性が必要なパラメーターの型について:

class B 
{
    public virtual void Frob(Giraffe g)
    {
    }
}
class D : B
{
    public override void Frob(Animal a)
    {
    }
}
....
B b = new D();
b.Frob(new Giraffe());  // Calls D.Frob, which takes any animal.

問題ありません。

残念ながら、C# は戻り値の型の共変性もパラメーターの型の反変性もサポートしていません。ごめん!

于 2010-11-10T00:46:02.047 に答える
2

まず、反分散を指定するためのインターフェースが必要です

public interface IBaseHandler<in T> where T : IBaseEvent
{
    void Handle(T handle);
}

次に、「基本的なこと」を行う基本クラスを定義できます

public class BaseType<T> : IBaseHandler<T> where T : IBaseEvent
{
    public virtual void Handle(T handle) { /* do base stuff */} 
}

これにより、 MoreDerivedEvent をオーバーライドできます

public class MoreDerivedType : BaseType<MoreDerivedEvent>
{
    public override void Handle(MoreDerivedEvent handle)
    {
        base.Handle(handle);
    }
}
于 2010-11-10T00:39:34.953 に答える