一、我們在使用C#的過程中,不可避免的用到了委托。
委托的本質是什么呢?
從語法上看,委托是對方法的抽象封裝,例如:public void print1(),public void print2(),我們可以抽象化,public delegate void Print();用Print p來聲明,委托需要實例化和調用,類似於c++中的函數模板;
從功能上看,委托主要是方法的指針,用以方便實現函數的回調、調用(異步等)。
直觀上,委托的作用有方法(函數)回調、方法(函數)接收值(listener),方法(函數)多線程調用、傳值等等。
本質上,delegate是一個類,同關鍵字class和interface平級的,這個類中包含方法所屬的類實例的地址、方法的地址,以及下個委托的引用(因此委托是鏈式結構的)。
以下我們以實例展開委托聲明、實例化、調用等技巧。
二、委托的聲明
C#中借用delegate關鍵字,C#的編譯器一遇到delegate,在翻譯C#的時候就被翻譯成類似於函數模板的東西。delegate刻意定義在類的內部,也可以定義在外部,和類沒有關系。
public delegate void Print(); //無參數,無返回值的委托 public delegate <out string>Print(); //無參數,返回string的委托 public delegate<out string,in string>Print(string str); //string參數,返回string的委托 .net3.5,系統定義了無參和有參的委托Action和Func關鍵字 public Action 本質就是public delegate void的轉定義 public Func 本質是public delegate <out string>
用法:
public Action<string> action; public Func<string> func;
委托的方法必須在形式上和委托的聲明一致
三、委托的賦值
public NoparamDelegate noParam = new NoparamDelegate(doSomething_forNoparamDelegate); //new 實現 public NoparamDelegate noparam_for_lambd = () => //lambd表達式直接賦值 { Console.WriteLine("no param,form lambd,test"); }; public NoparamDelegate noparam_for_function = doSomething_function; //方法直接賦值 public static void doSomething_forNoparamDelegate() { Console.WriteLine("no param,form test"); } public static void doSomething_function() { Console.WriteLine("no param,form function, test"); }
四、委托的調用
//委托調用-普通方法
doSomething();
//委托調用invoke
doSomething?.Invoke();
oneParam?.Invoke("one param,form test");
//異步調用
doSomething?.BeginInvoke(complete, null); //object標識附加信息 IAsyncResult ret = func_oneparam?.BeginInvoke("transmit賦值,異步調用,", null, null); //ret.IsCompleted, ret.AsyncWaitHandle.WaitOne(100)等用於輪詢過程 Console.WriteLine("開始其他工作!.."); string strRet = func_oneparam?.EndInvoke(ret); Console.WriteLine(strRet);
委托的BeginInvoke有兩個或三個參數(重載)
param1:string,參數
param2:回調函數,異步方法完成后調用
param3:object形式的附加信息
返回值:IAsyncResult 類型,我們記作ret
ret中有屬性IsCompleted和AsyncWaitHandle,可以用以輪詢異步方法調用的方法
string strRet = func_oneparam?.EndInvoke(ret); //在需要的地方獲取異步執行結果,如果沒執行完,將阻塞調用線程,直至獲取結果
五、委托鏈
對於多個委托方法,.net定義了委托鏈的概念
Delegate主要定義了Combine(簡寫+=),Remove(簡寫-=)等方法
Action delegateSet = null;
delegateSet = (Action)Delegate.Combine(actionChainOne,actionChainTwo);
下面是一段示例代碼:
public class Test { public delegate void Print(); Print p; public void method1() { Console.WriteLine("m 1"); } public void method2() { Console.WriteLine("m 2"); } public void method3() { Console.WriteLine("m 3"); } public void method4() { Console.WriteLine("m 4"); } public void combine() { p += method1; p += method2; p += method3; p += method4; } public void run() { Delegate[] myDelegates = p.GetInvocationList(); foreach (var myDelegate in myDelegates) { Print m1 = (Print)myDelegate;//注意此處需強轉 m1.Invoke(); } } } class Program { static void Main(string[] args) { Test test = new Test(); test.combine(); test.run(); Console.ReadKey(); } }
有交流溝通,請加群:568055323
