2


1

C# - フォームに勝つ - イベントフローサイクル

Jon SkeetのC#のrefcardを読んでいました。 彼は言い​​ました:

_ 「イベントはデリゲートと密接に関連していますが、同じものではありません。」 _

私の理解では、イベントが発生すると、ハンドラ(デリゲート)がコードを実行します。

次のような疑問があります。

*(1)イベントを宣言すると、それはいずれの "REGISTERS"に登録されますか?または「システム登録」?

(2)Old VB 6.0スタイルはデリゲートなしでイベントを処理するので、デリゲートなしでイベントを書くことができないのはなぜですか?

Winフォームの流れはどのようになりますか。ボタンをクリックすると、helloと表示されます(次の例)。

button_click( sender,some event args  )
{
    print();
}

void print( )
{
    console.WriteLine ("Hello");
}

このイベントフローはどのように内部的にリンクされ処理されますか? (CLRの内部で何が起きているのですか?)

(3)イベントが値を返すのを妨げるイベントの背後にある論理は何ですか?*

ゴールデンタイムを過ごしてくれてありがとう。

4 Answer


4


  • delegate *は型定義です。 メソッドが互換性を持たなければならないという署名を指定します。

  • event *はデリゲート型に基づくプロパティライクなクラスメンバです。 カプセル化を提供します。唯一のパブリックアクションは、ハンドラの追加(=)または削除( - =)です。

(1)いいえ、イベントはどこにも登録されていません。 ただし、取り扱い方法が登録されている場所です。

(2)VB6がどのように機能するかはわかりませんが、.NETではすべてのイベントがデリゲートに基づいています。

(2b)Buttonがクリックされたときに何が起きるかというと、button-codeはイベントがnullではないかどうかをチェックしてからメソッドを呼び出すということです。 イベントはその呼び出しリストを繰り返し処理し、登録されているすべてのハンドラを呼び出します。

もう少しありますが、ButtonClickは、ButtonイベントがMouseイベントまたはKeyboardイベント、あるいはその両方を処理および処理するときにButton自体によって生成されます。 これらのイベントはMessageLoop(Application.Run)から来ています。 しかしCLRレベルでは、これはMessageLoopがButton上でメソッド(Control.Perform(..))を呼び出すことを意味します。

(3)Valueを返すデリゲートやイベントを書くことができます。 しかし、複数のハンドラがある場合にそれが何を意味するのかを考えてください。 署名 `void handler(object sender、Eventargs e)`は(強い)推奨です。


1


イベントは*デリゲートを使って実装されます。

このコード:

公開イベントEventHandler YourEvent。

このようなものにコンパイルされます:

// a private field
private EventHandler YourEvent = null。

// public add_ method
[MethodImpl(MethodImplOptions.Synchronized)]
public void add_YourEvent(EventHandler value){YourEvent =(EventHandler)Delegate.Combine(YourEvent、value); }

// public remove_ method
[MethodImpl(MethodImplOptions.Synchronized)]
public void remove_YourEvent(EventHandler value){YourEvent =(EventHandler)Delegate.Remove(YourEvent、value); }

ですから、あなたがイベントを宣言するとき、あなたは実際にこれらの2つの関数を宣言します。 ご覧のとおり、これらの関数はデリゲートフィールドへのアクセスをカプセル化しています。 そのため、あなたはイベントにデリゲート値を割り当てることができず、購読または購読解除のみができません。

このコードは、イベントが次の構文を使用して宣言される理由を説明します。

公開イベントMyDelegate MyEvent {add {... }

削除{... }}

1)イベントはいかなる種類のレジストリにも登録されません。 デリゲートは参照型なので、イベント用のメモリ(プライベートデリゲートフィールド用)はヒープに割り当てられます。

2)イベントはデリゲートの上に構築されているので、デリゲートなしでそれらを使用することはできません。

3)3番目の質問は、Henk Holterman(1)および他の人々によって既に回答されています。

お役に立てれば。


0


  1. 私はこれについて知りません…​ しかし、私の最初の考えは、ほとんどのオブジェクトが存在し、イベントがオブジェクトの一部である場所なので、ヒープについてです。 しかし、私はこれについて推測しています…​.

  2. 彼らは実際にそうしますがあなたのために舞台裏で。 これはVBの機能です。

  3. それらは複数のデリゲート/リスナーを持つことができ、リスナーが起動されるときの順序は保証されていません。 規約は、eventargオブジェクトを使用して情報をハンドラに返すことです。 .NETに戻り値の型がないのはなぜですか?このことについてもう少し詳しく説明します。


0


1)いいえ、イベントハンドラは単純にイベント(ハンドラのリストを含む)に登録されます。

2)私はVB6にあまり精通していませんが、本質的にデリゲートは単なる強い型指定のメソッドポインタであるため、同様の仕組みを持っていると確信しています。

あなたの例では、 Button.Click`イベントはデリゲート button_click(送り側、いくつかのイベント引数) `への参照を含んでいます。 printへの参照は含まれておらず、呼び出す必要のあるメソッドへの参照だけが含まれています。

3)1つのイベントに対して複数のハンドラが存在する(またはまったく存在しない)可能性があるため、戻り値を持つことは非論理的な動作になることがよくあります。 そのため、ほとんどのイベントハンドラは `void`を返します。 そうは言っても、任意のシグネチャを持つことができるカスタムイベントを作成できます。 `void(object sender、EventArgs e)`シグニチャは、全部ではないにしても、ほとんどのMicrosoftイベントのベースシグニチャです。