質問

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

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 を必要としないとしましょう(何らかの理由で)、どの方法がより良い方法ですか?

役に立ちましたか?

解決

必要に応じて異なります。最初の例では、イベントハンドラーの副作用はメソッドスコープに制限され、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);
}

他のヒント

コードの他の場所にxが必要ない場合、ハンドラーはノーオペレーションです-確かにそれはナンセンスな状況です。

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top