イベント(イベント)は、委任に基づいて実装される一種の「通知メカニズム」です。たとえば、ボタンがクリックされると、それはイベントであり、イベントの発生は、処理のために関連するプログラムに通知することができます。イベントは、他の言語のコールバック関数、またはイベントリスナークラスと同等です。
Buttonクラスの場合、Clickはイベントを表す特別なプロパティの1つであり、そのタイプはEventHandler
デリゲートです。はい、イベントにはいくつかの重要なポイントがあります。
- クラスでイベントを定義します。イベントのタイプはデリゲートタイプです。
+=
このイベントを登録するための外部で、関連する外部メソッドを使用します- イベントソースが配置されているクラスでは、特定の条件下でこのデリゲートを呼び出す(つまり、イベントが発生する)ことは、実際には外部メソッドを呼び出すことです。これは、外部に通知することと同じです。呼び出しでは、イベントが発生したときの特定の詳細も渡されます。
カスタムイベント
イベントメカニズムの動作プロセスは次のとおりです。
イベントを処理するオブジェクトは、イベントを発行できるオブジェクトにイベントハンドラーを登録します。イベントが発生すると、登録されているすべてのイベントハンドラーが呼び出されます。イベントハンドラーは、デリゲートで表す必要があります。イベントは委任されたインスタンスと見なすことができますが、アプリケーションの利便性のために、C#は手数料に基づいていくつかの機能強化を行い、使用方法にいくつかの制限を設けています。カスタムイベントの手順は次のとおりです。
1.事件の声明
イベントは、クラス、構造、およびインターフェイスのメンバーです。宣言の形式は次のとおりです。
修饰符 event 委托类型名 事件名;
前記アクセス剤および変性剤は、他の修飾(例えばあってもよいstatic
、new
、abstract
等)。
2.イベントの登録と削除
イベント登録の目的は、イベントの送信者と通知が必要なオブジェクトを通知することです。たとえば、ボタンをクリックすると、特定の画像が拡大されます。イベント登録の本質は、デリゲートの呼び出しリストにメソッドを追加することです。
イベント+=
オペレーターを登録するには:
事件名 += 委托实例;
事件名 += new 委托类名(方法名);
使用-=
演算子用に登録されたイベントを削除します。
事件名 -= 委托实例;
事件名 -= new 委托类名(方法名);
なお、イベント外クラスのみイベントの動作に対して宣言、+=
及び-=
、むしろこのような割り当て(などの他の演算子を使用するよりも=
、それは空気か否かが判断される() ==
)などが挙げられます。
3.インシデントの発生
イベントの発生は、イベントに対応するデリゲートの呼び出し、つまり、デリゲートの呼び出しリストに含まれる各メソッドの呼び出しです。形式は次のとおりです。
事件名(参数);
イベントの典型的なアプリケーション
C#では、さまざまなデリゲートをイベントで使用できますが、通常のアプリケーションでは、デリゲートは通常次の形式になっています。
delegate void 委托名 (object sender, EventArgs e);
その中で、戻り値の型はですvoid
。デリゲート名には2つのパラメーターがあり、それぞれイベントの送信者と、イベントが発生したときのいくつかのパラメーターを表します。特定のパラメータを表現するには、通常、EventArgs
属性とメソッドを継承して追加する必要があります。
このように、カスタムイベントには6つのステップが必要です。
- ①から
EventArgs
継承できる特定のイベントパラメータタイプを定義します。 - ②デリゲートタイプを定義します。デリゲートをカスタマイズしたくない場合は、システムで定義されている汎用デリゲートを使用できます
EventHandler <TEventArgs>
。 - ③
event
キーワードとデリゲートタイプを使用して、イベントソースクラスでイベントを定義します。 - ④イベントソースクラスの適切な場所(つまり、イベントが発生したとき)で、イベントパラメータを生成し、イベントを呼び出します。
- ⑤イベントのサブスクライバーで、イベントが発生したときに実行されるタスクを示すイベントメソッドを記述します。メソッド名を記述しない場合は、ラムダ式または匿名メソッドを使用することもできます。
- ⑤
+=
この方法を使用してイベントを登録するイベントサブスクライバー。
この例DownloadWithEvent.cs
では、クローラープログラムは次のとおりです。
using System;
namespace ConsoleApp6事件_爬虫示例_
{
public delegate void DownloadStartHandler(object sender, DownloadStartEventArgs e); // 1.声明委托, 公用的
public delegate void DownloadEndHandler(object sender, DownloadEndEventArgs e);
public delegate void DownloadingHander(object sender, DownloadingEventArgs e);
public class DownloadStartEventArgs
{
public string Url {
get => _url; set => _url = value; }
private string _url;
public DownloadStartEventArgs(string url) {
this._url = url; }
}
public class DownloadEndEventArgs
{
public string Url {
get => _url; set => _url = value; }
private string _url;
public long ByteCount {
get => _byteCount; set => _byteCount = value; }
private long _byteCount;
public DownloadEndEventArgs(string url, long size) {
this._url = url; this._byteCount = size; }
}
public class DownloadingEventArgs
{
public string Url {
get => _url; set => _url = value; }
private string _url;
public double Percent {
get => _percent; set => _percent = value; }
private double _percent;
public DownloadingEventArgs(string url, double percent) {
this._url = url; this._percent = percent; }
}
public class Crawler
{
public event DownloadStartHandler DownloadStart; // 2.声明事件, 在一个类中
public event DownloadEndHandler DownloadEnd;
public event DownloadingHander Downloading;
public string Name {
get => name; set => name = value; }
private string name;
private string site;
public Crawler(string name, string site) {
this.name = name;
this.site = site;
}
public void Craw() {
while (true) {
string url = GetNextUrl();
if (url == null) break;
long size = GetSizeOfUrl(url);
//下载开始的事件发生
if (DownloadStart != null) {
DownloadStart(this, new DownloadStartEventArgs(url));
//Console.WriteLine("不为空------------------------");
} else
break;
for (long i = 0; i < size + 1024; i += 1024) {
// 下载数据...
System.Threading.Thread.Sleep(100);
double percent = (int)(i * 100.0 / size);
if (percent > 100) percent = 100;
//下载数据的事件发生
if (Downloading != null) {
Downloading(this, new DownloadingEventArgs(url, percent));
}
}
//下载结束的事件发生
if (DownloadEnd != null) {
DownloadEnd(this, new DownloadEndEventArgs(url, size));
}
}
}
private string GetNextUrl() {
int a = rnd.Next(10);
if (a == 0) return null;
return site + "/Page" + a + ".htm";
}
private long GetSizeOfUrl(string url) {
return rnd.Next(3000 * url.Length);
}
private Random rnd = new Random();
}
class Program
{
static void Main(string[] args) {
Console.WriteLine("Hello World!");
Crawler crawler = new Crawler("Crawer101", "http://www.gxust.edu.cn/");
// csharp1.0要写委托
crawler.DownloadStart += new DownloadStartHandler(ShowStart); // 3.注册事件, 在别的类中
crawler.DownloadEnd += new DownloadEndHandler(ShowEnd);
crawler.Downloading += new DownloadingHander(ShowPercent);
crawler.Craw();
}
private static void ShowStart(object sender, DownloadStartEventArgs e) {
Console.WriteLine((sender as Crawler).Name + "开始下载" + e.Url);
}
private static void ShowEnd(object sender, DownloadEndEventArgs e) {
Console.WriteLine("\n\r下载" + e.Url + "结束, 其下载" + e.ByteCount + "字节");
}
private static void ShowPercent(object sender, DownloadingEventArgs e) {
Console.WriteLine("\r下载" + e.Url + "......." + e.Percent + "%");
}
}
}
イベントの構文の詳細
C#イベントは、デリゲートに基づいて処理されます。デリゲートは、デリゲート型の変数または属性と見なすことができます。実際、イベントは単純な変数ではなく、重要な拡張機能であり、イベント宣言で宣言することもできます。次の形式のイベントのアクセサー:
修饰符 event 委托类型名 事件名
{
add{
... }
remove{
... }
}
イベントでのデリゲートのあるイベントのアクセス、追加や削除は、対応するアクセサがあるadd
とremove
。ではadd
とremove
アクセサ{}
は、タスクを完了するために書くことができます。イベント+=
を使用する-=
とき、およびオペレーターが実際にイベントアクセサーadd
とremove
メソッドを呼び出すとき。
実際、イベントが宣言されたときにイベントアクセサーが宣言されていない場合、コンパイラーは自動的にアクセサーを生成し、その形式は次のとおりです。
event D e
{
add{
e += value; }
remove{
e -= value; }
}
その中にD
は、デリゲート型の名前がvalue
あり、value
変数の意味は属性内の変数と同様であり、パラメーターを示します。宣言add
とremove
メソッドにより、イベントの処理がよりパーソナライズされます。ただしabstract
、イベントの場合、イベントアクセサーを宣言できないことに注意してください。
特に注意すべきは、イベント演算子のイベントアクセサーを宣言する場合は、+=
とのみにすることができるということ-=
です。