C# study notes event

Event (event) is a kind of "notification mechanism" implemented on the basis of delegation. For example, when a button is clicked, it is an event, and the occurrence of the event can be notified to related programs for processing. Events are equivalent to callback functions in other languages, or event listener classes.
For the Button class, Click is one of the special properties, which represents an event, and its type is EventHandlerdelegate. Yes, there are several key points about the event:

  • Define an event in a class, the type of the event is a delegate type
  • On the outside with +=to register this event, coming on an associated external method
  • In the class where the event source is located, calling this delegate under certain conditions (that is, the event occurs) is actually calling an external method, which is equivalent to notifying the outside. In the call, the specific details of when the event occurred are also passed.

Custom event

The working process of the event mechanism is as follows:
the object that cares about an event registers the event handler to the object that can emit the event. When an event occurs, all registered event handlers are called. The event handler must be represented by a delegate. It can be considered that events are delegated instances, but for the convenience of application, C# has made some enhancements on the basis of commissions, and has made some restrictions on the way of use. Here are some steps for custom events:

1. Statement of the incident

Events are members of classes, structures, and interfaces. The declaration format is as follows:

	修饰符 event 委托类型名 事件名;

Wherein the access modifiers and modifiers may be other modifiers (e.g. static, new, abstractetc.).

2. Event registration and removal

The purpose of event registration is to tell the sender of the event and the object that needs to be notified. For example, after the button is clicked, a certain picture will be enlarged. The essence of event registration is to add methods to the delegate's call list.
To register an event +=operators:

	事件名 += 委托实例;
	事件名 += new 委托类名(方法名);

Removes an event registered for use -=operators:

	事件名 -= 委托实例;
	事件名 -= new 委托类名(方法名);

Note that, in the event the outer class declarations, only with respect to the operation of the event +=and -=, rather than using other operators, such as assignment ( =), it is determined whether the air ( ==) and the like.

3. The occurrence of the incident

The occurrence of an event is the invocation of the delegate corresponding to the event, that is, the invocation of each method included in the delegate's invocation list. The format is as follows:

	事件名(参数);

Typical applications of events

C# allows various delegates to be used in events, but in typical applications, delegates are generally in this format:

delegate void 委托名 (object sender, EventArgs e);

Among them, the return type is void, the delegate name has two parameters, which respectively represent the sender of the event and some parameters when the event occurs. In order to express specific parameters, it is generally necessary to inherit EventArgsand add more attributes and methods.
In this way, a custom event must have six steps:

  • ① Define specific event parameter types, which can be EventArgsinherited from ;
  • ② Define a delegate type. If you don't want to customize the delegate, you can use the generic delegate defined in the system EventHandler <TEventArgs>;
  • ③ Define an event in the event source class, using eventkeywords and delegate types;
  • ④ In the appropriate place in the event source class (that is, when the event occurs), generate event parameters and call the event.
  • ⑤ In the subscribers of the event, write an event method to indicate the task being performed when the event occurs; if you do not write the method name, you can also use Lambda expressions or anonymous methods;
  • ⑥ In the event subscriber using +=this method to register the event.

In the example DownloadWithEvent.cs, the crawler program:

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 + "%");
		}
	}
}

Syntax details of the event

C# events are processed on the basis of delegation, which can be regarded as a variable or attribute with a delegate type. In fact, the event is not a simple variable, but an important extension, and in the event declaration You can also declare the accessor of the event in the following format:

	修饰符 event 委托类型名 事件名
	{
    
    
		add{
    
     ... }
		remove{
    
     ... }
	}

The access of the event, that is, the addition and removal of the delegate in the event, the corresponding accessor is addand remove. In addand removeaccessor {}, you can write to complete the task. When using the event +=and -=when the operator actually call event accessor addand removemethods.
In fact, if an event accessor is not declared when an event is declared, the compiler will automatically generate one, and its form is as follows:

	event D e 
	{
    
    
		add{
    
     e += value; }
		remove{
    
     e -= value; }
	}

Among them, Dis the name of the delegate type, and valuethe meaning of the valuevariable is similar to the variable in the attribute , indicating a parameter. Declarations addand removemethods make the handling of events more personalized. But note that for abstractevents, event accessors cannot be declared.
Of particular note is that if you declare an event accessor for event operators can only be +=and -=.

Guess you like

Origin blog.csdn.net/qq_45349225/article/details/114096121