C#深度學習の委托深度解析


一、我們在使用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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM