C#ヒューマンイベント



この深い意味を取り込んで掘り下げることは不可能です。基本的な、一見すると無限のC#のオープンスペースでイベントを勉強するのです。



イベント(.NETのフレームワークではない!)を勉強したとき、最終的にそれらがどのように配置され、構築されるべきかを理解するために多くのエネルギーを費やしました。 したがって、 ユーザーイベントの構造を理解するための方法論を公開することにしました 。これは、C#のイベントキーワードのようです。

すでに拷問されたMSDNを引用しませんが、明確かつ簡単に説明しようとします。





何を学ぶ必要があります:



イベントは状況に他なりません。イベントが発生すると、1つまたは複数のアクションが発生します。 ソフトウェアモデリングの言語では、 イベントは名前付きデリゲートであり、その呼び出し時に、イベントの呼び出し時に署名された特定の署名のすべてのメソッドが起動されます。 この解釈は、イベントの構造の本質全体を明らかにしますが、最初の「シャープなプログラム」を混乱させるだけでなく、プログラマーの頭に全体の意味を合理的に提示することを可能にしません。



したがって、 イベント 、これは発生する状況であり、いくつかのアクションが発生します。 イベント自体には特定の構造があります。



タスクが3つのクラスが定義されているとします。 最初のクラスは、ループを使用して100にカウントされます。 他の2つのクラスは、カウンターがカウントするのを待機します(たとえば、最初のクラスでは71にカウントされます)。 簡単に言えば、値71が検出されると、クラスごとにメソッドによってそれぞれ呼び出されます。 すべてを棚に置きましょう。



1.状況のモデリング。


これら3つの最も単純なクラスを準備し、 メインプログラムへのエントリポイントはそのままにします。

ClassCounterクラスと、カウントが行われるCount()メソッド。 (コードでは、名前空間namespaceを省略していますが 、これは日として明確です)。



class ClassCounter //  -    . { public void Count() { //    } }
      
      





他の2つのクラス( Handler_IおよびHandler_IIという名前) 。publicvoid Message()メソッドによってイベントに応答する必要があります。 合意された方法に従ってそれぞれ。



  class Handler_I // ,    (  71)    . { public void Message() { //  using System //     Console.WriteLine(" ,   71!"); } }
      
      





  class Handler_II { public void Message() { Console.WriteLine(",  71!"); } }
      
      





カウンターが100にカウントされて71に達すると、Handler_IクラスとHandler_IIクラスのMessage()メソッドが機能するはずです。

ClassCounterクラスに戻り、 forループを使用してカウンター変数int iを使用してカウンターを作成します。



  class ClassCounter //  -    . { public void Count() { for (int i = 0; i < 100; i++) { } } }
      
      





第1段階が完了しました。 カウンタークラスと、メッセージを表示する2つのクラスがあります。 タスク条件: i = 71になると、2つのクラスHandler_IおよびHandler_IIMessage()メソッドが機能するはずです。



2.イベントデザイン。


プログラミングから抽象化します。 作成するイベントは、「...カウンタがカウントされます。71になったらすぐにアクションを実行する必要があります。」というフレーズを表します。 したがって、「71に等しくなったらすぐに」条件が必要です。 条件付きifステートメントを使用して想像してください



  class ClassCounter //  -    . { public void Count() { for (int i = 0; i < 100; i++) { if (i == 71) { } } } }
      
      





イベントeventを構築します。 i = 71で機能するメソッド( シグネチャ) (またはプロトタイプ)を決定します。

メソッドの署名は、いわゆる仕様(または、簡単に言うと「テンプレート」)です。 1つまたは複数のメソッド。 メソッドが返す型名と入力パラメーターの型の名前の組み合わせです(順番に!順序は非常に重要です)。

たとえば、 int NewMethod(int x、char y)メソッドには署名int(int、char)があり、 void NewMethod()メソッドにはvoid(void)があります。

MSDNが解釈するように 、イベントはデリゲートに基づいており、デリゲートは非常に簡単に言えば 「メソッドへの参照を格納する変数」です。 すでに理解したように、 このイベントは、2つのvoid Message()メソッドを参照します。これらのメソッドの署名を決定し、この署名に基づいてデリゲートを作成する必要があります。 署名は次のようになります: void(void)



デリゲートを定義します(MethodContainerと呼びましょう):



  class ClassCounter //  -    . { //   ,     : //delegate < > (<  >); //   void Message().   ,   . public delegate void MethodContainer(); public void Count() { for (int i = 0; i < 100; i++) { if (i == 71) { } } } }
      
      





次に、キーワードeventを使用してイベントを作成し、このデリゲート( MethodContainer )に関連付けます。したがって、シグネチャvoid(void)を持つメソッドに関連付けます 。 イベントは公開する必要があります、なぜなら 何らかの方法で反応する必要のある異なるクラス(クラスHandler_IおよびHandler_II)で使用する必要があります。

イベントの構文は次のとおりです。public event <DeligentName> <EventName>;

デリゲート名は、メソッドが参照するデリゲートの名前です。



  class ClassCounter //  -    . { public delegate void MethodContainer(); // OnCount c   MethodContainer. public event MethodContainer onCount; public void Count() { for (int i = 0; i < 100; i++) { if (i == 71) { } } } }
      
      





i = 71の場合、onCountイベントを起動します。



 if (i == 71) { onCount(); }
      
      





それだけです イベントが作成されました 。 このイベントがトリガーするメソッドは署名によって識別され、デリゲートはそれらに基づいて作成されます。 次に、イベントはデリゲートに基づいて作成されます。 結局、どのメソッドが機能するかをonCountイベントに示します(署名のみを指定しました)。



3.サブスクリプション。


メインプログラムのエントリポイントに戻り、 ClassCounterクラスのインスタンスを作成します。 また、起動するクラスのインスタンスを作成します。 (これらはパブリックでなければなりません)。



  class Program { static void Main(string[] args) { ClassCounter Counter = new ClassCounter(); Handler_I Handler1 = new Handler_I(); Handler_II Handler2 = new Handler_II(); } }
      
      





次に、 起動するメソッドであるonCountイベントを示します。

これは、 <クラスまたはオブジェクト>。<イベント名> + = <メソッドを開始する必要があるクラス>。<署名に適したメソッド>のように発生します。

メソッドの後に括弧はありません! 私たちは彼を呼び出しませんが、単に彼の名前を示します。



  class Program { static void Main(string[] args) { ClassCounter Counter = new ClassCounter(); Handler_I Handler1 = new Handler_I(); Handler_II Handler2 = new Handler_II(); //   Counter.onCount += Handler1.Message; Counter.onCount += Handler2.Message; } }
      
      







検証


ClassCounterクラスのカウンターを開始し、iが71に等しくなるまで待機するようになりました。i= 71になるとすぐに、 onCountイベントがデリゲートMethodContainerによって発生します。



  class Program { static void Main(string[] args) { ClassCounter Counter = new ClassCounter(); Handler_I Handler1 = new Handler_I(); Handler_II Handler2 = new Handler_II(); Counter.onCount += Handler1.Message; Counter.onCount += Handler2.Message; //  Counter.Count(); } }
      
      





結果:

すでに71だからです!

まさに71!



おわりに


イベントを作成する意味と順序を理解してください。



イベントを作成(生成)するクラスはパブリッシャークラスと呼ばれ、メソッドが"+ ="でこのイベントをサブスクライブするクラスはサブスクライブされたクラスです。



覚えて! イベントをサブスクライブせず、そのデリゲートが空の場合、エラーが発生します。

これを回避するには、例に示すように、イベントをサブスクライブするか、まったく呼び出さないようにする必要があります(イベントはデリゲートであるため、不在は "null参照" nullです )。



  if (i == 71) { if (onCount != null) { onCount(); } }
      
      





演算子 " -= ":<ClassOrObject>。<EventName>-= <ClassCheyMethodMustStart>。<署名に適したメソッド>を使用して、いつでも登録解除できます。



イベントの利点は明らかです。イベントを生成するパブリッシャークラスは、 サブスクライブするクラスの数をサブスクライブまたはサブスクライブ解除する必要はありません。 彼は特定のメソッドのイベントを作成し、それらを特定の署名のデリゲートに制限しました。

イベントは、カスタムコントロールコンポーネント(ボタン、パネルなど)を構成するために広く使用されています。



最小の場合、問題が発生する可能性があります:動作するメソッドに入力パラメーター(または複数)がある場合はどうすればよいですか?

回答:イベントの基になっているデリゲートがすべてです。 より正確には、デリゲートに適したメソッドの署名。 パラメーターを持つメソッドを「受け入れる」デリゲートを作成すると、(!)イベントが開始されると、このパラメーターが要求されます。 当然、パラメーターは何でもかまいません。



.NETイベントに関するいくつかの言葉。 Microsoftは、デリゲートを構築するタスクを簡素化しました。.NETは、EventHandlerへの既製のデリゲートなどを提供します。 EventArgsの入力パラメーターの「パッケージ」。 イベントはいかがですか? 完成したEventHandlerを取得し、パラメーターで定義し、 クラスに「プッシュ」し、EventArgsからクラスを継承します。 そして-予定どおり)



多くの開発者は、イベントの「誤解」の主な問題はアプリケーションの特定の領域であり、結果として利用可能な例がほとんどないことを主張します(そして私はそれに同意します)。 さて、練習を忘れないでください。



PSデリゲートを使用したことがない場合は、デリゲートで練習してからこの記事を理解してください。

この困難なトピックに少し理解を深めていただければ幸いです。 頑張って!



All Articles