Unity C#筆記 委托/事件/Action/Func/Lambda表達式



C#里的委托相當於C#的函數接口對象(C語言可稱為函數指針,C++可稱為函數對象),是C#的一個比較重要的特性。

而觀察者模式是一種常見的設計模式,在C#里往往使用委托等相關語法搭配來實現觀察者模式。

因此很需要搞懂 delegate(委托),event(事件),Action/Func的語法及區別。
此外觀察者模式的原理很易懂,不作多講,本文純粹用於記錄C#委托/時間/Lambda表達式語法。

delegate(委托)

//聲明沒有參數,沒有返回值的委托類型XXXX
public delegate void XXXX();

聲明一個委托類型(類似typedef XXXX C++/C的函數類型)

注:不是產生一個對象。

然后利用聲明出來的委托類型,我們可以利用它的對象,賦予其對應類型的函數。
從而實現出類似調用函數指針的效果。

//委托類型XXXX的對象
public XXXX delegateObj1;

public void func1(){}
public void func2(){}
public void func3(int a){}
//可將某個同樣類型的函數賦給該對象
delegateObj1 = func1;

//調用委托對象等同於調用它代表的函數
delegateObj1();//等價於func1();

delegateObj1 = func2;
delegateObj1();//等價於func2();

delegateObj1 = func3;//類型不匹配,語法錯誤

event(事件)

單純用委托的話只能一對一調用(一次調用,一個函數觸發)。

而通過利用事件機制,我們可以實現一對多的調用(一次調用,多個相關事件(函數)觸發)。

而且它添加/移除委托對象(相當於觀察者模式里的觀察者)的操作十分方便,使用+=或-=即可。

//先聲明一個委托類型
public delegate void XXXX();
//委托事件對象
public event XXXX EventObj1;//此處比一般委托多了個event
EventObj1 += func1; //添加
EventObj1 += func2; //添加

EventObj1(); //調用func1(),func2()

EventObj1 -= func1; //移除
EventObj1(); //調用func2()

Action/Func

Action/Func主要是為了簡化委托(delegate)語法,它們本質都是委托。

//無返還值,不帶參數的委托對象
public delegate void XXXX();
public XXXX obj1;

在上面我們看到委托語法,必須為委托類型命名(聲明委托),才能使用該委托類型。

但是使用Action/Func可以無需聲明委托類型的語句,直接利用Action<...>/Func<...>來用自己想要的委托類型。

Action和Func的源碼底層實際也是delegate的封裝

  • Action<...>用於無返還值的委托類型
  • Func<...,T>用於有返回值的委托類型,最后一個類型參數 T 代表返還值類型。
//無返還值,不帶參數的委托對象
public Action obj3;
//無返還值,帶int參數的委托對象
public Action<int> obj4;

//double返還值,無參數的委托對象
public Func<double> obj5;
//int返還值,帶string,double參數的委托對象
public Func<string,double,int> obj6;

//將Action應用至事件
public event Action<int> EventObj1;
EventObj1 += obj4;
EventObj1 += func1;
EventObj1 += func2;
EventObj1();//調用obj4(),func1(),func2()

Lambda表達式

Lambda表達式是用於簡便快速寫簡單函數的語法,而且這些函數往往要用於委托對象。

Lambda表達式基本形式:

(參數...) => { 函數內容... }

參數在它的類型可自動推導的情況下,才可以省略參數類型。如果謹慎起見,可以不省略,從而避免隱式類型轉換。

Action obj1;
obj1 = () => { Debug.Log("FGNB"); };

Action<int> obj2;
obj2 = (int x) => { Debug.Log(x); };
obj2 = (x) => { Debug.Log(x+233); };//也可以省略參數類型

Func<int,int> obj3 = (int x) => { return x; };

結論

  • 為了簡化語法,可使用Action/Func而不是直接使用delegate,除非你想強調特殊的委托類型。
  • 實現觀察者模式,可以使用event和委托(Action/Func/delegate)搭配。更加完善的做法則是再搭配Dictionary,通過Key找到想要的委托事件對象列表,然后可以添加/移除/通知該對象的觀察者。
  • Lambda表達式適用於快速編寫簡短的函數,復雜的函數應該做成類方法方便調試。


免責聲明!

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



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