一. 委托的分類 通過用什麼類型的方法來聲明為委托,可以分為兩類: 1. 委托靜態方法:把一個靜態方法給委托 2. 委托實例方法:把一個實例對象的成員方法給委托 (這兩個名字是博主取的,可能不是很專業只是為了好區分) 二. 原理部分 委托是將函數指針和實例對象打包在一起的類,它有兩個重要的成員,一個 ...
一. 委托的分類
通過用什麼類型的方法來聲明為委托,可以分為兩類:
1. 委托靜態方法:把一個靜態方法給委托
2. 委托實例方法:把一個實例對象的成員方法給委托
(這兩個名字是博主取的,可能不是很專業只是為了好區分)
二. 原理部分
委托是將函數指針和實例對象打包在一起的類,它有兩個重要的成員,一個用來保存實例對象,一個用來保存函數的指針。從源碼中我們可以查看System.Delegate,如下:
1. 將會調用方法所在的對象
// _target is the object we will invoke on [System.Security.SecurityCritical] internal Object _target;
2. 將會調用的方法指針
// _methodPtr is a pointer to the method we will invoke // It could be a small thunk if this is a static or UM call [System.Security.SecurityCritical] internal IntPtr _methodPtr;
另外,我們查看System.Delegate的屬性,我們可以看到一個屬性 Target
public Object Target { get { return GetTarget(); } }
來看一下這個 GetTarget() 方法的功能
[System.Security.SecuritySafeCritical] internal virtual Object GetTarget() { return (_methodPtrAux.IsNull()) ? _target : null; }
可以看到這邊有一個欄位 _methodPtrAux,這是一個IntPtr類型的指針,可以看到註釋可以看出,當把一個靜態方法給委托的時候,將會返回一個 null,如果是一個實例方法的時候,將會返回當前方法所在的實例對象(this)
// In the case of a static method passed to a delegate, this field stores // whatever _methodPtr would have stored: and _methodPtr points to a // small thunk which removes the "this" pointer before going on // to _methodPtrAux. [System.Security.SecurityCritical] internal IntPtr _methodPtrAux;
三. 測試代碼
測試類 Test.cs:
public class Test { /// <summary> /// 實例方法 /// </summary> public void ShowHelloWorld1() { Console.WriteLine("Hello World! -- 1"); } /// <summary> /// 靜態方法 /// </summary> public static void ShowHelloWorld2() { Console.WriteLine("Hello World! -- 2"); } }
委托聲明:
public delegate void ShowHelloWorldMethod();
上端測試代碼:
//聲明測試對象 Test test = new Test(); //構造實例方法的委托 ShowHelloWorldMethod del = test.ShowHelloWorld1; //判斷一下Target是不是指向方法所在的對象 Console.WriteLine(del.Target is Test);//True //調用一下 ((Test)del.Target).ShowHelloWorld1();//Hello World! -- 1 //構造靜態方法的委托 ShowHelloWorldMethod del2 = Test.ShowHelloWorld2; //判斷一下Target是不是null Console.WriteLine(del2.Target == null);//true
測試結果符合我們的預期:
四. 總結
如果委托的Target屬性為null說明是靜態方法的委托,如果委托的Target屬性不為null說明是實例方法的委托。