2

ベストプラクティスとは何かについての一般的な質問:

public void Foo()
{
    int x = 5;
    myControl.Click += (o, e) =>
    {
        x = 6;
    };
}

xラムダ イベント ハンドラ内で変数を使用していることに注意してください。

また:

public class Bar
{
    private int x = 5;
    public void Foo()
    {
        Control myControl = new Control();
        myControl.Click += new EventHandler(myControl_Click);
    }

    private void myControl_Click(object sender, EventArgs e)
    {
        x = 6;
    }
}

ここでxは、クラスのプライベート メンバーであるため、イベント ハンドラーでアクセスできます。

xここで、(何らかの理由で) コードの他の場所は必要ないとしましょう。どの方法がより良い方法でしょうか?

4

2 に答える 2

3

それはあなたの必要性に依存します。最初の例では、イベント ハンドラーの副作用はメソッド スコープに制限され、2 番目の例では、副作用はインスタンス スコープです。X はどこにも使用されていないため、最初の例でクロージャーを使用しても意味がないと思います。そのため、例に基づいて判断するのは困難です。

そうは言っても、通常は、(コードで作成した) イベント ハンドラーを変数と同様に扱うのが最善です。範囲をできるだけ狭くし、必要に応じてより広い範囲にリファクタリングします。

クロージャーを使用する必要がある場合を強調するより良い例は次のとおりです。

public void Subscribe(Action<string> messageCallBack)
{
    myButton.Click += () => messageCallBack("Button was clicked.");
}

これにより、複数のサブスクライバーが可能になり、別の方法よりもはるかに簡単になります。

private readonly List<Action<string>> callBacks;
public MyClass()
{
    callBacks = new List<Action<string>>();
    myButton.Click += myButton_Click;
}

private myButton_Click(object sender, EventArgs e)
{
    foreach (Action<string> callBack in callBacks)
    {
        callBack("Button was clicked");
    }
}

public void Subscribe(Action<string> messageCallBack)
{
    callBacks.Add(messageCallBack);
}
于 2009-01-08T15:55:21.867 に答える
1

コードのどこにも x が必要ない場合、ハンドラーはノーオペレーションです。つまり、これはナンセンスな状況です。

xが必要になったら、それを Bar インスタンスまたはデリゲート インスタンス (またはデリゲートのコレクション) のどちらにスコープするかを決定する必要があります。

于 2009-01-08T15:52:44.447 に答える