eventとは?イベントの発生とハンドリングの仕組み

このQ&Aのポイント
  • イベントとは、「あるアクションが発生したことを自動的に通知するための仕組み」と本にあります。さらに、「送信側オブジェクトのイベント(と呼ばれるクラスメンバーに、受信側のイベントハンドラー(と呼ばれるメソッド)を登録します。」とあります。
  • evt.SomeEvent += Handler; は、イベントハンドラーをイベントに登録しています。evtが持っているSomeEventイベントにHandlerメソッドを関連づけることで、イベントが発生した時にHandlerメソッドが実行されるようになります。
  • ボタンをクリックした時に、イベントの発生元のオブジェクトから情報が送られてきます。この情報はsender引数で受け取ることができます。また、イベントの補足情報はe引数で受け取ることができます。イベントハンドラーの中でこの情報を使って必要な処理を行うことができます。
回答を見る
  • ベストアンサー

eventの概念が理解できません

こんにちは。オブジェクト志向でVB、C#を学んでいます。デリゲートを理解してeventについて学んでいますが、よく理解できません。 イベントとは、「あるアクションが発生したことを自動的に通知するための仕組み」と本にあります。 さらに、「送信側オブジェクトのイベント(と呼ばれるクラスメンバーに、受信側のイベントハンドラー(と呼ばれるメソッド)を登録します。」とあります。 下記が本に載っているコードです。 私が理解できているのは、 ・戻り値が無し、引数をとらないメソッドを参照するオブジェクト。MyEventHandlerというデリゲートを宣言 ・戻り値が無し、引数をとらないメソッドを参照するオブジェクト。SomeEvent変数を宣言 ・MyEvent型のevt変数の宣言 理解できないのは、 evt.SomeEvent += Handler;。何をやっているかわかりません。 ここをわかりやすくお教え頂けませんでしょうか? using System; //MyEventHandler型を宣言。ここは理解できます。 delegate void MyEventHandler(); class MyEvent{ //イベントの宣言。EventHandler型の変数、SomeEvent。 public event MyEventHandler SomeEvent; public void Fire(){ if(SomeEvent !=null) SomeEvent(); } } class EventDemo{ static void Handler(){ //←イベントハンドラー Console.WriteLine("Event occurred"); } static void Main(){ MyEvent evt = new MyEvent(); evt.SomeEvent += Handler; evt.Fire(); } } また、もう一点お教え下さい。フォーム上のボタンをクリックした時に、メッセージを表示するようなイベントはどのような形で動いているのでしょうか? senderはイベントの発生元のオブジェクトがそのまま入っていて、eはイベントの補足情報が入っているのは理解しました。 ボタンをクリックした時に、ボタンクラスから何らかの情報が送られてきて、それをsenderとeで受取ると思うのですが、これのどこにeventとデリゲートが関わってくるのでしょうか? 何かモヤモヤしてeventがわかりません。 宜しくお願い致します。 private void btn_Click(object sender, EventArgs e) { messagebox.show("hello"); }

質問者が選んだベストアンサー

  • ベストアンサー
  • shockatz
  • ベストアンサー率80% (153/191)
回答No.1

自分が最初に理解できた記事はこれです。 http://www.atmarkit.co.jp/fdotnet/csharp_abc/csharp_abc_013/csharp_abc01.html イベント駆動型のプログラミングはjavascriptなどでは一般的ですが、関数起動のタイミングを宣言しているだけのもので、C#やVBとは次元が違います。 イベントの意義は、「発生元」が、その内容を「利用先」に通知しなくていい、という一言につきます。 「利用先」が任意に発生したり、消去されたりする場合や、複数存在する場合は本当に便利です。 「利用先」が一定時間ごとに、「発生元」のイベント状態をチェックする「ポーリング」と呼ばれる古臭い手法も必要なく、コードがスッキリして性能が上がります。 イベントを複数の「利用先」に共通して通知するための「型」がデリゲートです。 デリゲート自体は、イベント専用の概念ではなく、デリゲートを使用しなくともイベントの定義や、「利用先」でのイベントハンドラの定義は可能です。 .NETはこういう場合、即席にデリゲートを作ってイベントを伝搬するのですが、この自動生成デリゲートは冗長で非常に効率が悪いため、一般的には専用のデリゲートを定義します。 (通知先が1つでパラメタが単純なら、デリゲートを定義しなくても特に性能低下はないですが) デリゲートは一種の「関数引数の型」であり、内部的にやっていることは、一時的に引数のインスタンスを作って、そのポインタをイベントとともにディスパッチャ(交換手)に通知しているというイメージでしょうか。 なお、ボタンクリックの例では、Object sender, EventArgs eという引数を取るデリゲートがすでに内部に宣言されているため、それを使ってイベントが伝搬されます。 受ける側は単に、イベント側と同じデリゲート(型)で定義したメソッドを用意し、それをイベントに関連付ければいいので、非常にシンプルです。

fflashing
質問者

お礼

ご回答ありがとうございました!お教え頂いたリンク先は大変わかりやすいものでした。感謝です!

関連するQ&A

  • イベントevt?evt.target:event.srcElement;の意味合い

    以下の理解で合っているのでしょうか? よくイベントの取得で エレメント.onclick = function(evt){ var e = evt?evt.target:event.srcElement; } でeにイベントオブジェクトの発生元要素をセットしているのを見かけますが、 これは、ブラウザーの違いの吸収なのでしょうか? firefoxでは、イベントハンドラー関数にイベントオブジェクトが渡されるので、渡されたイベントオブジェクトよりevt.targetで発生元要素をセットし、一方IEでは、eventという名前のオブジェクトが存在している(?)ので、イベントハンドラー関数にイベントオブジェクトが渡されず、event.srcElementで発生元要素をセットする。  ※Opera、Safariは何でも良い IEの場合、後から、イベントが追加されたらeventオブジェクトはどうなるのでしょうか?ある要素の一つのイベントタイプには一つのイベントハンドラーしか定義できないのでしょうか?

  • イベントハンドラ関数について

    現在VC++/CLR 2005 でプログラミングをしています。 基本的な事柄かもしれませんが、質問させてください  以下の2つのボタンのイベントハンドラ関数があった場合 //ボタン1のイベントハンドラ関数 private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) String^ str = textBox1->Text } //ボタン2のイベントハンドラ関数 private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { } ボタン2をクリックしたときの動作とボタン1の動作を同じにしたいと思っています。 その場合は private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) String^ str = textBox1->Text } //ボタン2のイベントハンドラ関数 private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { String^ str = textBox1->Text } のようにボタン2のイベントハンドラ関数をボタン1と同じように書けばいいのですが イベントハンドラ関数の処理が膨大になった場合を考えて省略する 書き方は無いのでしょうか?(以下の場合ですとエラーが起こってしまいます。) private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { button1_Click(); } 宜しくお願いします

  • デリゲートとイベントの関係(VB.NET2005)

    VB2005の本に書いてある内容が理解できません。 誰か助けてください! ---------- イベントとデリゲートの仕組み  .NETイベントが内部ではデリゲートとして処理されることを理解すれば、その威力を存分に引き出すことができます。 もう少し厳密に言うと、イベントを発行するクラスには、そのイベントをサブスクライブするクライアントすべてをポイントする、プライベートデリゲートフィールドが定義されています。 イベントが発行されると、.NETのイベントインフラストラクチャによって該当するデリゲートフィールドのInvokeメソッドが呼び出されます。そして、Invokeメソッドからすべてのクライアントにイベントが通知されます。  このことは、.NET Frameworkで定義されているイベントごとに対応するデリゲートが存在することからもうかがい知ることができます。 [オブジェクトブラウザ]を使用すれば、それを確認できます。 たとえば、第2引数としてEventArgsオブジェクトを受け取るイベントはすべて、内部ではSystem.EventHandlerデリゲートを通じて管理されます。 ほとんどのWindowsフォームコントロールが公開するKeyPressイベントは、KeyPressEventHandlerデリゲートによって処理されますが、このデリゲートは、第1引数としてObject、第2引数としてKeyPressEventArgsオブジェクトを受け取るSubプロシージャをポイントします。 ---------- 全体的にちんぷんかんぷんですが特に「サブスクライブ」などがわかりません よろしくお願いします。

  • C#のデリゲートを用いたイベントで戻り値を付けたい

    C#のデリゲートを用いたイベントで イベントハンドラに戻り値がある場合は どのように記述すればよいのでしょうか。 以下のコードでは(A)のところで error CS0029: 型 'void' を型 'string'に暗黙的に変換できません。 というエラーになります。 --------------------------------------- //sample.cs //イベントハンドラ(戻り値あり) using System; namespace My {  delegate string MyDelegate();  class MainClass  {   public static void Main()   {    string msg;    MyClass mc = new MyClass();    MyEventClass mec = new MyEventClass();    mec.eventname += new MyDelegate(mc.myget);    msg = mec.Oneventname(); // <--------(A) //  msg = (string)mec.Oneventname();    Console.WriteLine(msg);   }  }    class MyClass  {   public string myget()   {    string msg;    msg = "イベントハンドラが呼び出されました";    return msg;   }  }  class MyEventClass  {   public event MyDelegate eventname;   public void Oneventname() // public string Oneventname()   {    if(eventname != null)    {     eventname(); //   return eventname();    }   }  } } ---------------------------------------

  • 実行時にコントロールのイベントの登録/解除を、イベントハンドラのメソッドをあらかじめ知っていないロジックから実施する方法

    実行時にコントロールのイベントの登録/解除を、イベントハンドラのメソッドをあらかじめ知っていないロジックから実施する方法 通常、実行時にコントロールにイベントの登録/解除 を行う際は。 AddHandler 対象コントロール.イベント名, AddressOf メソッド RemoveHandler 対象コントロール.イベント名, AddressOf メソッド や AddHandler 対象コントロール.イベント名, メソッドのデリゲート型 RemoveHandler 対象コントロール.イベント名, メソッドのデリゲート型 を行うと思います。 しかし、この方法では、これを実施するロジックが AddressOf メソッド や メソッドのデリゲート型 を知っていなければなりません。 そうではなく、それをあらかじめ、知っていなくても 対象コントロール から AddressOf メソッド や メソッドのデリゲート型 に該当するオブジェクトを取得するなどして、 実施できる方法を教えてください。 言語は、.NET系であれば。。 VB.NET, C#, C++のいづれかでもよいです。 できさえすればよいです。 J#とか、Delphi.NETとかマイナーなのは、厳しいです。 なお、C++でもしできるのであれば。 2003のマネージC++と、 2005のC++/CLIの両方について知りたいです。 以上、よろしくお願いします。

  • c# イベント用デリゲートの引数

     こんにちは。c#初心者です。  今回はイベントに用いるためのデリゲートの引数に関する質問です。  通常、「System.Windows.Forms.Control」のイベントで用いられているデリゲートの引数は全て  void SampleHandler(object sender, SampleEventArgs e)  のようになっていますが、コントロール以外のクラス(System.Windows.Forms.Controlから派生しないクラス)、例えばコレクションクラスのようなものでも同じように「EventHandler<T>」デリゲートを使わなければならないのでしょうか?  それともう一つ質問です。コントロールクラスでのイベントの引数は  SampleHandler(object sender, …  のようにせずに  SampleHandler(SampleControl sender, …   としてはいけないのでしょうか? (いけないと思いますが…)  質問は以上の2点です。どなたか詳しい方がいらっしゃいましたら教えていただけませんか?

  • .NETの SerialPortクラスでデータ受信イベントを処理するには?

    こんばんは。いつもお世話になっております。 Visual C++ 2005でSerialPortクラスを使ってシリアル通信をしたいのですが、データ受信イベントハンドラをどのように扱えばよいか分からず困っていますのでご教示ください。 HelpやMSDN、インターネット上で検索をして見つかるのはC#の例ばかりで、C++でどのように記述するのかが見つかりませんでした。 イベントやデリゲートなど、.NETで導入された(であろう)概念が出てきたり、^(ケット)記号が出てきたりと戸惑うことも多いのですが、きっと serialPort1->DataReceived += gcnew イベントハンドラを登録; // イベントハンドラの本体 private: System::Void serialPort1_DataReceived(System::Object^ sender, System::EventArgs^ e){ ほげほげ; } みたいな感じで書くのではないかと予想しています。 Visual Basic 6.0 でのシリアル通信はずっと使ってきました。 C/C++は使い始めて10年弱、C++/CLIは未経験です。(似て非なる言語?) よろしくお願いします。

  • オブジェクトとイベントにつきまして

    javascript超初心者です。。 今仮に、スクリプトの中でメソッド、プロパティ、イベントやイベントハンドラの前に、オブジェクトを入れるとします。(たとえば、window.aleart~など) その中でも、イベントやイベントハンドラをスクリプトの中に書くとして、ナビゲーターオブジェクトをその前に書く時、documentなのかwindowなのか、また他のオブジェクトなのか、使い分け方が分かりません。 大変稚拙な質問で申し訳ありませんが、javascriptの先輩方、どういうイベント(イベントハンドラ)の時にwindowで、どういうイベント(イベントハンドラ)の時にdocumentなのか等、ご回答頂けると本当に助かります。 どうぞよろしくお願い致します。

  • JButton配列でのイベント処理

    JAVA初心者です。 ある、画面にボタン50個を作成しました。(JButtonの配列で作成しました。) そこで質問です。下記のコールバックメソッド(?)btnActionPerformedを50個分作成するのは 煩雑なので1つで処理しようと考えております。 for (int cnt=0; cnt<50; cnt++) { ... JButtonのインスタンス生成処理等 ... btn[cnt-1].addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { btnActionPerformed(evt); } }); } ... ... ... private void btnActionPerformed(java.awt.event.ActionEvent evt) { ... } btnActionPerformedで受け取ったevtパラメータから押されたボタンのプロパティ等 が判別つくのでしょうか?ActionEventクラスのヘルプを参照しましたが、 いまひとつ良くわかりません。 また、このevtパラメータを使う方法以外で、この様な事が実現できる方法が あれば教えてください。よろしくお願いします。

    • ベストアンサー
    • Java
  • 戻り値で返したオブジェクトの寿命について

    Ruby初心者です。 【前置き】 メソッドで宣言した変数(以下arr)に値(以下[1,2,3])を代入し戻り値として返した場合、 メソッドの戻り値(以下retArr)には、[1,2,3]への参照(arr.object_id)が設定されると認識しております。 ----------------------- def method arr = [1,2,3] return arr end retArr = method() ----------------------- 【質問】 C言語の場合、関数内で宣言したローカル変数のアドレスを戻り値として返却した場合、 関数を抜けた時点で、そのアドレスの内容は保障されなくなりますが、 1.Rubyではその様な問題がなく動作するのは、何故でしょうか? 2.また、メソッド内で宣言したオブジェクト(上記[1,2,3])の寿命はいつまでなのでしょうか? 【備考】 いろいろと調べてみたのですが、オブジェクトの参照(object_id)は、ポインタに近い概念であることは記載されているのですが、その仕組みを理解できずに悩んでします。

    • ベストアンサー
    • Ruby