3

私の質問(ジェネリック メソッドの再利用可能な非ジェネリック メソッド) によると、提供されたソリューションを実装しましたが、いくつかのリファクタリング (コードを基本クラスに移動) の後、コードが理解できない StackOverflowException になります。

への呼び出しは、呼び出されてから呼び出されますHandle(new TestCommand())が、継承されたクラスを呼び出す代わりに、再度呼び出します。IMessageHandler.Handle(IMessage)Handle<TMessage>(TMessage)Handle(TestCommand message)IMessageHandler.Handle(IMessage)

ジェネリック メソッドの as-cast toIMessageHandler<TestCommand>が機能します。そうでない場合は、 が呼び出されますHandleUnknownMessage(IMessage)

説明するのが難しいので、代わりにここに私の TestCode を示します。

class Program {
    static void Main(string[] args) {

        MyProcess p = new MyProcess();
        IMessageHandler handler = p;

        handler.Handle(new DummyCommand()); // works -> HandleUnknownMessage gets called as expected

        handler.Handle(new TestCommand());  // fails -> results in a StackOverflowException 
    }
}  

public abstract class ProcessBase : IMessageHandler {
    void IMessageHandler.Handle(IMessage message) {
        System.Diagnostics.Debug.WriteLine("Dynamic Message gets handled");
        dynamic dynamicMessage = message;

        Handle(dynamicMessage);
    }

    private void Handle<TMessage>(TMessage message) where TMessage : IMessage {
        System.Diagnostics.Debug.WriteLine("Generic Message gets handled");
        var handler = this as IMessageHandler<TMessage>;
        if (handler == null)
            HandleUnknownMessage(message);
        else
            handler.Handle(message);
    }

    protected virtual void HandleUnknownMessage(IMessage unknownMessage) {
        System.Diagnostics.Debug.WriteLine("Unknown message {0} passed to Process".FormatWith(unknownMessage.GetType()));
        // Handle unknown message types here.
    }
}

public class MyProcess : ProcessBase, IMessageHandler<TestCommand>, IMessageHandler<TestEvent> {

    public void Handle(TestCommand commandMessage) {
        System.Diagnostics.Debug.WriteLine("TestCommand gets handled");
    }

    public void Handle(TestEvent eventMessage) {
        System.Diagnostics.Debug.WriteLine("TestEvent gets handled");
    }
}

public class DummyCommand : IMessage {    }

public class TestCommand : IMessage {    }

基本クラスのコードを に配置するProcessBaseMyProcess、コードは問題なく動作します。ジェネリック メソッドおよび継承と組み合わせて dynamic キーワードを使用する際に制限はありますか?

4

1 に答える 1

3

メソッドで定義してみてくださいIMessageHandler<TMessage>void Handle<TMessage>(TMessage message)

定義されていないため、MyProcess.Handle定義したイベントはそのクラスにのみ属し、実装するインターフェイスには属しません。コードが を呼び出そうとするとき、それが実際にそれらの特定のメソッドを持つ でIMessageHandler<TMessage> handlerあることを知りません。MyProcessインターフェイス メソッドを追加すると、呼び出し解決は、それらのメソッドが存在することを認識し、それらMyProcessを呼び出す必要があります。IMessageHandler.Handle(IMessage)それ以外の場合は、無限ループを生成する次善の方法を呼び出すだけです。

于 2012-12-18T12:20:18.223 に答える