3

.NETでイベントを処理するための推奨/推奨される方法はどれですか。

this.Load += new EventHandler(Form1_Load);
private void Form1_Load(object sender, EventArgs e)
{ }

また

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
}

各方法の長所/短所は何でしょうか?私は何年にもわたって両方の方法を使用してきましたが、通常は最初の方法に傾倒しています。これは、VisualStudioがイベントを処理するために自動的に作成する方法だからです。私が見逃している2番目の方法に何か利点はありますか?

4

5 に答える 5

8

最初の方法は、Microsoftが提案するものです。パターンは次のとおりです。

  1. 一部のコードはイベントを発生させたい、OnXxxを呼び出します
  2. OnXxxはデリゲートに電話をかけます
  3. 有線イベントハンドラーは呼び出されます

2番目のモデルを実行すると、base.OnXxx呼び出しを忘れて、すべてを壊してしまうリスクがあります。オプション2の優れた点は、他のすべてのイベントハンドラーの前に呼び出されるか後に呼び出されるかを決定できることです。コードをbase.OnXxxの前に置くと、イベントが実行される前に実行されます。もちろん、最初のモデルはいつでも使用でき、2番目のモデルは、イベントを発生させるクラスをサブクラス化する場合にのみ使用できます。

于 2009-02-11T16:21:40.627 に答える
5

それはあなたがイベントをどこでキャッチしたいか、そしてその理由に完全に依存します。

最初のメソッド(ワイヤアップ)は、他のクラスにイベントを処理させたい場合に使用します。そして、あなたはいくつかの理由でそれをする必要があるかもしれません。他のクラスは、複雑なロジックなどを実行するサービスにアクセスできる場合があります。重要なのは、別のオブザーバーにイベントに応答させたい場合は、最初の方法を使用することです。

2番目の方法(オーバーライド)は、フォームに応答させたい場合に使用します。責任はローカルだからです。

于 2009-02-11T16:20:04.220 に答える
1

元の質問ではありませんが、次のことを指摘したいと思います。

this.Load += new EventHandler(Form1_Load);

次のように記述できます。

this.Load += Form1_Load;

デリゲートの構築が推論されます。

于 2009-02-11T16:31:48.683 に答える
0

厳格なルールはありませんが、どちらのアプローチにも落とし穴があります。簡単に回避できるものを選択します。

デリゲート

多くの開発者は += コードを繰り返し呼び出される場所に配置します。少なくとも多くの初心者はそうしています。その結果、所有者コントロールによって維持されるデリゲート リストに 'n' 個のエントリがあり、それらすべてが呼び出されます。回避する簡単な方法は、一度だけ呼び出されるコンストラクターのような場所に += 呼び出しを配置することです。

オンXXXX

base.XXX メソッドの呼び出しを忘れるリスクがあります。これはバグの一般的な原因であり、ほとんどの Windows プログラマーは、基本クラス バージョンの呼び出しに失敗した場合の問題を認識しています。これは、Windows メッセージ (ペイントなど) の場合に特に当てはまります。

于 2009-02-11T16:46:26.637 に答える
-1

オーバーライドされたメソッドは、呼び出されるため優先されます多形的に実質的に CLR によって。

[編集] オーバーライドされたメソッドが望ましいと私が考える理由は次のとおりです。

以下に簡単な例を示します。

class Foo
{
    public event EventHandler Changed = delegate { };

    protected virtual void OnChanged()
    {
        this.Changed(this, EventArgs.Empty);
    }
}

class Bar : Foo
{
    public Bar()
    {
        this.Changed += new EventHandler(this.Bar_Changed);
    }

    void Bar_Changed(Object sender, EventArgs e) { }
}

class Baz : Foo
{
    protected override void OnChanged() 
    { 
        base.OnChanged();
    }
}

今、私はこれBazがより良い実装であると信じています。ここにその理由があります。 Barイベントを接続するには、次の IL 命令を実行する必要があります。

    L_000a: ldftn instance void Bar::Bar_Changed(object, class [mscorlib]System.EventArgs)
    L_0010: newobj instance void [mscorlib]System.EventHandler::.ctor(object, native int)
    L_0015: call instance void Foo::add_Changed(class [mscorlib]System.EventHandler)

のインスタンスである処理メソッドへのデリゲートを作成し、基本クラスのイベントでメソッドをEventHandler呼び出す必要があります。add_Changedこれらはパフォーマンス キラーではありませんが、動作するために以前のコードは必要ありませんBaz。への呼び出しOnChangedはすべて仮想であるため、CLR が継承チェーンで呼び出す正しいインスタンス メソッドを見つけることだけがパフォーマンスの低下となります。

于 2009-02-11T16:17:19.390 に答える