4

検討

    Action _captureAction;
    private void TestSimpleCapturedAction()
    {
        Action action = new Action(delegate { });
        Action printAction = () => Console.WriteLine("Printing...");

        action += printAction;
        CaptureActionFromParam(action);
        action -= printAction;

        _captureAction(); //printAction will be called!
    }

    private void CaptureActionFromParam(Action action)
    {
        _captureAction = () => action();
    }

printActionが_captureActionによって呼び出される理由は、その行が

action -= printAction;

実際に変換します

action = (Action) Delegate.Remove(action, printAction);

したがって、CaptureActionFromParam()の_captureActionによってキャプチャされたアクションは変更されません。つまり、TestSimpleCapturedAction()のローカルの「action」変数のみが影響を受けます。

このようなシナリオでの私の望ましい動作は、printActionが呼び出されないことです。私が考えることができる唯一の解決策は、新しい「デリゲートコンテナ」クラスをそのように定義することです。

    class ActionContainer
    {
        public Action Action = new Action(delegate { });
    }

    private void TestCapturedActionContainer()
    {
        var actionContainer = new ActionContainer();
        Action printAction = () => Console.WriteLine("Printing...");

        actionContainer.Action += printAction;
        CaptureInvoker(actionContainer);
        actionContainer.Action -= printAction;

        _captureAction();
    }

    private void CaptureInvoker(ActionContainer actionContainer)
    {
        _captureAction = () => actionContainer.Action();
    }

これは機能しますが、この新しい抽象化レイヤーを導入しなくても、希望する動作を実現できるのではないかと思います。戦略パターンを実装すると、そのような状況に簡単につながる可能性があるため、言語を考慮したり、BCLが何らかの形でネイティブにサポートしたりします。

ありがとう !

4

1 に答える 1

7

デリゲートは文字列のようなものです。これらは参照型として実装されますが、不変の値型のように動作します。文字列に文字を加算または減算しても、文字列は変更されず、新しい結果である新しい文字列が生成されます。整数に数値を加算または減算しても、整数は変更されず、新しい結果である新しい整数が生成されます。また、デリゲートをデリゲートから追加または減算しても、どちらのデリゲートも変更されません。結果である新しいデリゲートを生成します。

キャプチャしたいものが変化する可能性のあるデリゲートである場合は、デリゲートへの参照を含む変数をキャプチャします。変数はさまざまであるため、「変数」と呼ばれます。変化する可能性のあるものが必要な場合は、変数を取得します。

    CaptureActionFromParam(()=>{action();}); 

これで、キャプチャされたデリゲート自体が、たまたまその中にある値ではなく、変数「アクション」をキャプチャしました。

覚えて:

  • パラメータは値で渡されます
  • ラムダは値ではなく変数をキャプチャします。

わかる?

于 2010-02-20T18:31:40.963 に答える