C# study notes commission

Delegate and event are unique concepts proposed in C#. Simply put, delegate is a better implementation of "function pointer" in C#, and event is a better implementation of "callback function" in C# .


Delegation type and assignment

It can be considered that the delegate is similar to the function pointer, it is a reference type, and it refers to the function. The function referenced by the delegate has a certain type. A delegate type represents the signature of the function (the parameter type and order of the function), so it can be considered type-safe, that is, a delegate type cannot reference any type that is incompatible with it; A delegate instance can represent a specific function, as well as an instance method or static method of a certain class, so the delegate can be understood as a package or reference of a function.

1. Declaration of delegate types and delegate variables

The declaration format is as follows:

修饰符 delegate 返回类型 委托名 (参数列表);

The formal parameter list specifies the signature of the delegate, and the result type specifies the return type of the delegate.
Example:

public delegate double MyDelegate(double x);

This declares a delegate type, called a MyDelegatetype, and the function it can reference is like this: it takes a doubleparameter and the return type is also double.
Since the delegate is a type, it is generally parallel to classthe declaration , so don't write it classin the definition. (If it is written classinside, it becomes a nested type.)
Declaring a variable of a delegate type is the same as declaring an ordinary variable:

	委托类型名 委托变量名;

Such as:

	MyDelegate d;

2. The instantiation of the delegate

The method of instantiating a delegate and creating an instance of a delegate is as follows:

	new 委托类型名(方法名);

The method name can be a static method name of a certain class, or an instance method name of an object instance. E.g:

	MyDelegate d1 = new MyDelegate(System.Math.Sqrt);
	MyDelegate d2 = new MyDelegate(obj.MyMethod);

The signature and return value type of the method here must be consistent with those declared by the delegate type, that is, the delegate is type-strict and type-safe.

Shorthand for delegated assignment (syntax sugar): In C# 2.0 and above, it can be abbreviated as:

	MyDelegate d1 = System.Math.Sqrt;
	MyDelegate d2 = obj.MyMethod;

3. Delegate call

An important feature of the delegate is that the delegate does not need to care about the type of object to which the method belongs when calling a method. It only requires that the signature of the provided method matches the signature of the delegate.

In the example DelegateIntergral.cs, calculate the integral of the mathematical function:

delegate double Fun (double x);
class DelegateIntegral 
{
    
    
	static void Main (string[] args) {
    
    
	Console.WriteLine ("Hello World!");

	Fun fun = new Fun (Math.Sin);
	double d = Integral (fun, 0, Math.PI / 2, 1e-4);
	Console.WriteLine (d);

	Fun fun1 = new Fun (Linear);
	double d1 = Integral (fun1, 0, 2, 1e-3);
	Console.WriteLine (d1);

	Rnd rnd = new Rnd ();
	double d2 = Integral (new Fun (rnd.Num), 0, 1, 1e-2);
	Console.WriteLine (d2);

	}

	public static double Linear (double a) {
    
    
		return a * 2 + 1;
	}

	public static double Integral (Fun f, double a, double b, double eps) {
    
       // 积分计算 
		int n, k;
		double fa, fb, h, t1, p, s, x, t = 0;

		fa = f (a);
		fb = f (b);

		// 迭代初值
		n = 1;
		h = b - a;
		t1 = h * (fa + fb) / 2.0;
		p = double.MaxValue;

		// 迭代计算
		while (p >= eps) {
    
    
			s = 0.0;
			for (int i = 0; i < n; i++) {
    
    
				x = a + (i + 0.5) * h;
				s += f (x);
			}
			t = (t1 + h * s) / 2.0;
			p = Math.Abs (t1 - t);
			t1 = t;
			n += n;
			h /= 2.0;
		}
		return t;
	}
}

class Rnd 
{
    
    
	Random r = new Random ();
	public double Num (double x) {
    
    
		return r.NextDouble ();
	}
}

4. Entrusted merger (multicast)

Delegates are not just a wrapper for function pointers. Using mergeable delegates has far better functions than function pointers in other languages.

The combinability of delegates is also called multicast. Simply put, multiple functions can be called at once. The merged delegate is actually a packaging of multiple functions, and the call to such a delegate is actually all the calls to each packaged function. Many of these functions are collectively referred to as the call list of the delegate.

In fact, the compiler translates all delegates into System.MulticastDelegatesubclasses, and delegate calls are translated into Invoke()method calls.

The result of the commissioned addition and subtraction operation, if it does not contain a function, the result is null. When calling a delegate that is equal to null, an NullReferenceExceptionexception will occur at runtime , so before calling a delegate, it should be judged whether it is null.
Example DelegateMulticast.csusing multicast delegation:

delegate void D(int x);
class DelegateMulticast
{
    
    
	static void Main(string[] args) {
    
    
		Console.WriteLine("Hello World!");
		DelegateMulticast.Test();
	}
	public static void M1(int i) {
    
    
		Console.WriteLine("DelegateMulticast.M1: " + i);
	}
	public static void M2(int i) {
    
    
		Console.WriteLine("DelegateMulticast.M2: " + i);
	}
	public void M3(int i) {
    
    
		Console.WriteLine("DelegateMulticast.M3: " + i);
	}

	public static void Test() {
    
    
		D cd1 = new D(DelegateMulticast.M1);
		cd1(-1);		// call M1

		D cd2 = new D(DelegateMulticast.M2);
		cd2(-2);		// call M2

		D cd3 = cd1 + cd2;
		cd3(10);		// call M1 then M2

		cd3 += cd1;
		cd3(20);		// call M1, M2, then M1

		DelegateMulticast d = new DelegateMulticast();
		D cd4 = new D(d.M3);
		cd3 += cd4;
		cd3(30);		// call M1, M2, M1, then M3

		cd3 -= cd1;		// remove last M1
		cd3(40);		// call M1, M2, then M3

		cd3 -= cd4;
		cd3(50);		// call M1 then M2

		cd3 -= cd2;
		cd3(60);		// call M1

		cd3 -= cd2;		// impossible removal is benign
		cd3(60);		// call M1

		Console.WriteLine(cd3 == null);    // False
		cd3 -= cd1;		// invocation list is empty
		Console.WriteLine(cd3 == null);    // True

		//cd3 (70);		// System.NullReferenceException thrown

		cd3 -= cd1;		// impossible removal
		Console.WriteLine(cd3 == null);    // True
	}
}

5. Commissioned conversion and equality

Any delegate type is implicitly System.MulticastDelegatederived from it. System.MulticastDelegateClass members can be accessed by using member access . But System.MulticastDelegateit is not a delegate type, it is a class type. The delegate type is implicitly sealed, that is, it cannot be derived from the delegate type.

The delegate types in C# are name-equivalent, not structurally equivalent. In other words, two delegate types with different names, even if they have the same signature and the same return type, are still considered to be different delegate types. Such as:

delegate void D(int a);
delegate void E(int a);

Then D and E are two different types of delegates, and they cannot be converted to each other.

For two delegate instances , the equality operator ( ==) has a special meaning. This is because each delegate type implicitly provides predefined comparison operators. Two delegate instances are considered equal in the following situations:

  • Both are nullor they are references to the same delegate instance.
  • If there is only one method in the delegate, they point to the same static method or the same instance method of the same object.
  • If there are only multiple methods in the delegate, the number of methods is the same, the corresponding methods are the same, and the order is the same.

According to the above definition, different types of commissions may also be equal.
Example DelegateEqual.cs determines whether two delegates are equal:

delegate void D(int a);
delegate void E(int a);
class DelegateEqual
{
    
    
	public static void M(int a) {
    
     }
	public static void Test() {
    
    
		E e = new E(M);
		D d = new D(M);
		e += e;
		d += d;
		//e = (E)d;		// 编译错误
		//d += e;

		Console.WriteLine(d.Equals(e));
		//Console.WriteLine(d == e);      // why??? 编译错误?
		Console.WriteLine(d);
	}
}

Guess you like

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