C# デリゲート、イベント理解の概要

黄舟
リリース: 2016-12-21 14:54:05
オリジナル
999 人が閲覧しました

目次

l はじめに

l 委任とは

l イベントの理解

l イベントのキーワード

l 最後に



はじめに

C# でデリゲートとイベントを学習する過程で、それらが何であるか、そしてそれらをどのように使用するかを理解するための記事がたくさんあります。ここで、私が学んだすべての側面を理解する必要があるものを以下に説明します:-)。

委任とは何ですか?

委任とイベントの 2 つの概念は完全に互換性があります。デリゲートは単なる関数ポインターです。つまり、アドレスを渡すことで関数を参照できます。デリゲートは、インスタンス化するときに参照関数をパラメーターとしてコンストラクターに提供するクラスです。

各デリゲートには独自の署名があります。例: Delegate int SomeDelegate(string s, bool b); は、デリゲート SomeDelegate が string 型と bool 型の仮パラメータを持ち、int を返すことを意味します。タイプ。

上記: デリゲートをインスタンス化するときは、そのコンストラクターにパラメーターとして参照関数を提供します。ここで注意してください: 参照される関数はデリゲートと同じ署名を持つ必要があります。

次の関数を見てください:

PRivate int SomeFunction(string str, bool bln){...}

これらは類似したシグネチャを持っているため、この関数を SomeDelegate のコンストラクターに渡すことができます (言い換えると、それらはすべて同じパラメータの型と番号を指定し、同じデータ型を返します)。

SomeDelegate sd = new SomeDelegate(SomeFunction);

sd は SomeFunction を指します。つまり、sd を呼び出すと、関数 SomeFunction も呼び出されます。の、後で使用します。

さて、デリゲートの使用方法を理解する必要があります。引き続きイベント ジャーニーを理解しましょう...

イベントの理解

C# では次のことがわかります:

l ボタンは、クリックするとクラスになりますをクリックすると、クリック イベントがトリガーされます。

l クロック (Timer) もクラスです。ミリ秒ごとにティック イベントがトリガーされます。


次のようなプロットがあると仮定して、例を通して学習してみましょう:

ここで、メソッド CountTo(int countTo, int reverseableNum) を持つ Counter クラスがあります。これは、次のことを意味します: 指定された期間内 ( 0 ~~countTo)、指定された時点に達すると、NumberReached イベントがトリガーされます。

これには、デリゲート型の変数である NumberReached というイベントもあります。意味: イベントに名前を付ける場合は、以下に示すように、イベント キーワードと使用するデリゲートの型を指定して宣言します。



上記の宣言では、NumberReachedEventHandle は単なるデリゲートです。正確な表現は NumberReachedDelegate である必要があります。しかし、Microsoft は、MouseDelegate または PaintDelegate をこのように考えることはなく、タイトルは MouseEventHandler または PaintEventHandler です。

NumberReachedEventHandler は NumberReachedDelegate よりも便利そうに思えますね? さて、続きましょう。イベントを宣言する前に、次の形式でデリゲートを定義する必要があります:

public delegate void NumberReachedEventHandler(object sender, NumberReachedEventArgs e );

次に、void 戻り値と object と NumberReachedEventArgs の 2 つの仮パラメータを持つデリゲート NumberReachedEventHandle を宣言します。セクション 1 で強調したように、デリゲートをインスタンス化する場合、引数として渡される関数もデリゲートと同じシグネチャを持つ必要があります。

コード内で、マウスの移動位置を決定するために PaintEventArgs または MouseEventArgs を使用しましたか? Paint イベントをトリガーしたオブジェクトの Graphics プロパティを使用したことがありますか?実際、ユーザーにデータを提供するクラスはすべて、イベント パラメーター クラスと呼ばれる System.EventArgs クラスを継承します。イベントがパラメーターを提供しない場合、このクラスは定義されません。私たちの場合、次のクラスを通じて予想される時点を提供します。

public class NumberReachedEventArgs : EventArgs

{

private int _reached;

public NumberReachedEventArgs(int num)

{

this._reached = num;

public int ReachedNumber

{

get

return _reached; Counter クラスの内部を見てみましょう:

namespace Events

{

パブリックデリゲート void NumberReachedEventHandler(object送信者、



//

} u Public Void Countto (Int Countto, Int Reachablenum) {

IF (Counto & LT; Reachablenum)

Throw New ArgumentedException (

Reachab Lenum は countto ") より小さい必要があります;
for (int ctr=0;ctr<=countTo;ctr++)

NumberReachedEventArgs e);これ以上

}}}}









)

{{{ NumberReached(this, e);// イベントを発生させる

}

}

}

}

Counter では、指定された時点に到達すると、次の点に注意する必要があります。l NumberReached (NumberReachedEventHandler デリゲートのインスタンス) を呼び出して、トリガー イベントを完了します。

NumberReached(this, e); このようにして、登録されたすべての関数を呼び出すことができます。

l NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum); を通じて、登録されているすべての関数のイベント データを提供します。

l 上記のコードを読んだ後、次のコードの代わりに OnNumberReached(NumberReachedEventArgs e) メソッドを直接使用して NumberReached(this, e) を呼び出すのはなぜでしょうか?

if(ctr ==到達可能なNum)

{

NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum)

//OnNumberReached(e);

if(NumberReached != null ) e);//イベント

}

return;//これ以上カウントしない

}

これは良い質問なので、OnNumberReached 署名をもう一度見てみましょう:

protected virtual void OnNumberReached(NumberReachedEventArgs e)

① また、キーワード protected により、このクラスを継承するクラスのみがこのクラス内のすべてのメソッドを呼び出すことができるように制限されることも理解しました。

②キーワード virtual は、このメソッドが継承されたクラスでオーバーライドできることを示します。

これら 2 つの点は非常に便利です。Counter を継承するクラスを作成すると、OnNumberReached メソッドをオーバーライドすることで、イベントがトリガーされる前に他の作業を実行できます。



protected override void OnNumberReached(NumberReachedEventArgs e)

{

//追加の作業を行います

Base.OnNumberReached(e)

}

注: Base.On NumberReached(e) を呼び出さない場合、その後、このイベントは決してトリガーされません。これは、クラスを継承し、その他のイベントの一部を除外する場合に便利です。

l デリゲート NumberReachedEventHandler はクラス定義の外側、名前空間内で定義され、すべてのクラスから見えることにも注意してください。

さて、実際に Counter クラスを使用してみましょう。



私たちの単純なアプリケーションには、2 つのテキスト ボックス、つまり txtCountTo と txtReachable があります。




以下は btnRun のクリック イベントです:

private void btnRun_Click(object sender, System.EventArgs e)
️ vert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable .Text));

}



イベントを初期化するための構文処理は次のとおりです:

oCounter = 新しいカウンター(); ocounter.numberreached += new numberreachedeventhandler(ocounter_numberreached);

= の代わりに += を使用していることにも注意してください。これは、デリゲートが複数のオブジェクトを参照できる特別なオブジェクトであるためです (ここでは、複数の関数を参照できることを意味します)。たとえば、oCounter_NumberReached と同じシグネチャを持つ別の関数 oCounter_NumberReached2 がある場合、両方の関数を参照できます。oCounter.NumberReached += new NumberReachedEventHandler(oCounter_NumberReached2);

ここで、イベントがトリガーされた後、上記の 2 つの関数が順番に呼び出されます。



状況に応じて、NumberReached イベントの発生後に oCounter_NumberReached2 が呼び出されないようにする場合は、次のように記述するだけです: oCounter.NumberReached -= new NumberReachedEventHandler(oCounter_NumberReached2);



最後に、参照用の完全なソース コード:


Form1.cs


using System.Drawing;
using System.ComponentModel;
using System.Data; ;

namespace Events
{
/**//// <概要> 
/// Form1 の概要説明。 
///  
パブリック クラス Form1 : System.Windows.Forms.Form
{
Counter oCounter = null; 

プライベート System.Windows.Forms.Button cmdRun; 
プライベート System.Windows.Forms.TextBox txtReachable; 
プライベート System.Windows.Forms.TextBox txtCountTo; 
プライベート System.Windows.Forms.Label label1; 
プライベート System.Windows.Forms.Label label2; 
private System.Windows.Forms.Button btnRemoveDelegate; 
/**////


コンテナコンポーネント = null; public Form1()
izeComponent();
oCounter = new Counter(); ed += new ‐NumberReachedEventHandler(oCounter_NumberReached); / 使用中のリソースをクリーンアップします。 if (コンポーネント ! = null) );        }

Windows フォーム デザイナーが生成したコード#region Windows フォーム デザイナーが生成したコード
/**////  
/// デザイナー サポートに必要なメソッド - コード エディターでこのメソッドの内容を
/// 変更しないでください。 
///
 
private void InitializeComponent()
{
this.cmdRun = new System.Windows.Forms.Button(); 
this.txtReachable = new System.Windows.Forms.TextBox(); 
this.txtCountTo = new System.Windows.Forms.TextBox(); 
this.label1 = 新しい System.Windows.Forms.Label(); 
this.label2 = 新しい System.Windows.Forms.Label(); 
this.btnRemoveDelegate = new System.Windows.Forms.Button(); 
this.SuspendLayout(); 
//
// cmdRun
//
this.cmdRun.Location = new System.Drawing.Point(16, 72); 
this.cmdRun.Name = "cmdRun"; 
this.cmdRun.Size = new System.Drawing.Size(48, 23); 
this.cmdRun.TabIndex = 2; 
this.cmdRun.Text = "実行"; 
this.cmdRun.Click += new System.EventHandler(this.cmdRun_Click); 
//
// txtReachable
//
this.txtReachable.Location = new System.Drawing.Point(144, 40); 
this.txtReachable.Name = "txtReachable"; 
this.txtReachable.Size = new System.Drawing.Size(56, 20); 
this.txtReachable.TabIndex = 1; 
this.txtReachable.Text = ""; 
//
// txtCountTo
//
this.txtCountTo.Location = new System.Drawing.Point(144, 16); 
this.txtCountTo.Name = "txtCountTo"; 
this.txtCountTo.Size = new System.Drawing.Size(56, 20); 
this.txtCountTo.TabIndex = 0; 
this.txtCountTo.Text = ""; 
//
// label1
//
this.label1.AutoSize = true; 
            this.label1.Location = 新しい System.Drawing.Point(16, 16); 
this.label1.Name = "label1"; 
this.label1.Size = new System.Drawing.Size(51, 13); 
this.label1.TabIndex = 3; 
this.label1.Text = "カウントする"; 
//
// label2
//
this.label2.AutoSize = true; 
this.label2.Location = new System.Drawing.Point(16, 40); 
this.label2.Name = "label2"; 
this.label2.Size = new System.Drawing.Size(99, 13); 
this.label2.TabIndex = 4; 
this.label2.Text = "この番号に到達します"; 
//
// btnRemoveDelegate
//
this.btnRemoveDelegate.Location = new System.Drawing.Point(16, 104); 
this.btnRemoveDelegate.Name = "btnRemoveDelegate"; 
this.btnRemoveDelegate.Size = new System.Drawing.Size(168, 23); 
this.btnRemoveDelegate.TabIndex = 5; 
this.btnRemoveDelegate.Text = "2 番目のハンドラーを削除"; 
this.btnRemoveDelegate.Click += new System.EventHandler(this.btnRemoveDelegate_Click); 
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); 
this.ClientSize = new System.Drawing.Size(224, 134); 
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.bt nRemoveDelegate、
this.label2、
this.label1、
                                                                          this.txtCountTo、
this.txtReachable、
this.cmdRun}); 
this.Name = "Form1"; 
this.Text = "イベント"; 
this.ResumeLayout(false); 

}
#endregion

/**////  
/// アプリケーションのメイン エントリ ポイント。 
///
 
[STAThread]
static void Main()
{
Application.Run(new Form1()); 
}

private void btnRun_Click(object sender, System.EventArgs e)
{
if(txtCountTo.Text == "" || txtReachable.Text=="")
戻る。 
oCounter.CountTo(Convert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable.Text)); 
}

private void oCounter_NumberReached(オブジェクト送信者, NumberReachedEventArgs e)
{
MessageBox.Show("Reached: " + e.ReachedNumber.ToString()); 
}
private void oCounter_NumberReached2(object sender, NumberReachedEventArgs e)
{
MessageBox.Show("Reached2: " + e.ReachedNumber.ToString()); 
}

private void btnRemoveDelegate_Click(object sender, System.EventArgs e)
{
oCounter.NumberReached -= new NumberReachedEventHandler(oCounter_NumberReached2); 
oCounter.CountTo(Convert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable.Text)); 
}
}
}







Counter.cs




システムを使用しています。 

namespace Events
{
public delegate void NumberReachedEventHandler(object sender, NumberReachedEventArgs e); 

    /**////  
/// カウンターの概要説明。 
///  
パブリック クラス Counter
{
パブリック イベント NumberReachedEventHandler NumberReached; 

public Counter()
{
//
// TODO: ここにコンストラクターロジックを追加します
//
}
public void CountTo(int countTo, int reverseableNum)
{
if(countTo throw new ArgumentException (「reachableNum は countTo より小さい必要があります」); : NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum); 
OnNumberReached(e); 
return;//これ以上カウントしない
}
}
}

protected virtual void OnNumberReached(NumberReachedEventAr gs e)
{
if(NumberReached!=null)
{
NumberReached(this, e); 
}
}
}

public class NumberReachedEventArgs : EventArgs
{
private int _reached; 
public NumberReachedEventArgs(int num)
{
this._reached = num; 
}
public int ReachedNumber
{
get
{
return _reached; 
}
}
}
}

以上は C# 委任、イベント理解入门の内容、さらなる相关内容请关注 PHP中文网(www.php.cn)!

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!