全面講解:委托、事件


每個編程者在項目中必定繞不開的話題:委托和事件。對於初學者來說,總會感覺有些難以理解,或者說無法自己隨意運用。本文對委托、事件做一個詳細的講解,即是基礎知識的自我溫故,同時亦是記錄。篇幅有些長,如果認真閱讀,相信你會有所收獲。

《Introducing Visual C# 2010》(Adam Freeman著,Apress出版)一書的第10章中有這樣的介紹:

Delegates are special types thatencapsulate a method, similar to function pointers found in other programminglanguages. Delegates have a number of uses in C#, but you are most likely toencounter a special type of delegate—the event. Events make notifyinginterested parties simple and flexible, and I’ll explain the convention fortheir use later in the chapter.

委托是封裝方法的特殊類型,它類似於其它編程語言中的函數指針。委托在C#中有大量運用,但你最可能遇到的是一種特殊的委托類型— 事件。事件使得對相關部件的通知變得簡單而靈活,本章后面將解釋其使用約定。

I’ll also explain the Func and Action typesthat let you use delegates in a more convenient form and that are usedextensively in some of the latest C# language features, such as parallelprogramming. We’ll finish up this chapter with a look at anonymous methods andlambda expressions, two C# features that let us implement delegates withouthaving to define methods in our classes.

我也會解釋Func和Action類型,它們讓你以更方便的形式使用委托,而且在一些最新的C#特性中也有廣泛使用,如並行編程。本章最后考察匿名方法和lambda表達式,這是讓我們不必在類中定義方法就可以使用委托的兩個C#特性。

 

委托:

委托定義:將函數作為另一個函數的參數進行調用。另外的解釋:當一個類或者是進程需要調用另外一個方法時,需要借助另外的類或者是進程進行調用,這種機制稱為委托。網上有大牛說:委托可以理解為函數指針,不同的是委托是面向對象、類型安全的。

實現步驟:

1、聲明一個委托類型:

public delegate int CalculateDelegate(int x, int y);

2、定義一個委托對象:

CalculateDelegate calculateDelegate = new CalculateDelegate(Add);

其中Add是委托封裝的方法;

3、執行委托方法:

calculateDelegate(2, 3);

其中委托綁定的方法Add:

public static int Add(int x, int y)
{ return x + y;}

 

事件:

事件是一種特殊類型的委托

拿winform中button雙擊舉例說明委托可能更加貼切:

聲明一個委托,並聲明一個事件:

public delegate void EventHandler(object sender, EventArgs e);
public event EventHandler Click;

綁定一個事件:

this.button1.Click += new System.EventHandler(this.button1_Click);

this.button1_Click是一個方法:

private void button1_Click(object sender, EventArgs e){}

 

拿一個實際項目舉例說明:

匿名方法:

匿名方法(Anonymous methods) 提供了一種傳遞代碼塊作為委托參數的技術。匿名方法是沒有名稱只有主體的方法。在匿名方法中您不需要指定返回類型,它是從方法主體內的 return 語句推斷的。

在之前講解委托時寫到綁定方法:

CalculateDelegate calculateDelegate = new CalculateDelegate(Add);
public static int Add(int x, int y)
{
return x + y;
}

如果使用匿名方法重寫上面的代碼:

CalculateDelegate calculateDelegate = delegate(int x, int y){return x + y;};

可見:匿名方法綁定委托直接省去了編寫一個單獨的方法,使得代碼更為簡潔。

項目中,使用委托時,很多時候編輯器會幫助我們把方法直接放入合適的委托對象中,但有時候編輯器幫助不了我們,比如:Control.Dispatcher.Invoke(delegate). 例如:

this.btnExit .Dispatcher .Invoke (new Action(() => {}));

 

Lambda表達式:

Lambda 表達式是一種匿名函數,簡單地說,它是沒有聲明的方法,也即沒有訪問修飾符、返回值聲明和名字;

C#的Lambda 表達式都使用 Lambda 運算符 =>,該運算符讀為“goes to”。語法如下:

(object argOne, object argTwo) => {; /*Your statement goes here*/}

用Lambda表達式重寫上面使用匿名方法編寫的委托實例,在匿名方法的基礎上,編寫如下:

方式一:

CalculateDelegate calculateDelegate = (int x, int y) => { return x + y; };

方式二,更簡單的表達:

CalculateDelegate calculateDelegate = (x, y) => { return x + y; };

方式三,再簡單:

CalculateDelegate calculateDelegate = (x, y) => x + y;

從上面可以看出,Lambda僅僅是在匿名方法的基礎上加上 => 符號,但是卻讓整個代碼實現起來顯得更為優雅。 

 

泛型委托:

在.net平台下有Microsoft自帶的泛型委托,如:Action,Action<T>,Fun<T>等。實際使用中,如果需要用到泛型委托,系統內置的委托基本上就能滿足需求了,下面一一介紹它們的原型及調用實例。

Action

系統封裝的Action委托,沒有參數沒有返回值。調用實例為:

public delegate void Action();
static void Main(string[] args)       
{
  Action action = new Action(Method);
  action();
}
private static void Method()
{
  Console.WriteLine("i am is a action");
}

如果方法的表達很簡單,可以使用Lambda表達式,代碼如下: 

Action action = () => { Console.WriteLine("i am is a action"); };

 

Action<T>

系統封裝的Action<T>委托,有參數但是沒有返回值。調用實例為:

public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
static void Main(string[] args)        
{
  Action<int,int> action = new Action<int,int>(Method);
  action(2,3);
}
private static void Method(int x,int y)
{
  Console.WriteLine("i am is a action");
}

 

使用Lambda表達式編寫Action<T>代碼如下:

Action<int, int> action = (x, y) => { Console.WriteLine("i am is a action"); };

 

Fun<T>

系統封裝的Fun<T>委托,有返回值。調用實例為:

public delegate TResult Fun<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
static void Main(string[] args) 
{
  Fun<int, int, bool> fun = new Fun<int, int, bool>(Method);
  bool ret = fun(2,3);
}
private static bool Method(int x,int y)
{

  if (x + y == 5) return true;
  else return false;
}

 

使用Lambda表達式編寫Fun<T>,代碼如下:

Fun<int, int, bool> fun = (x, y) =>            
{
  if (x + y == 5) return true;
  else return false;
};

 

Fun<T>沒有參數有返回值的情況:

Fun<bool> fun = () =>    
{
  int x = 4;
  int y = 3;
  if (x + y == 5) return true;
  else return false;
}; //也可以如此編寫Fun<bool> fun = () => false;

  

多播委托:

最后說下多播委托,所謂多播委托,即 “多路廣播委托”(MulticastDelegate)。從它的名字就可以看出,此種委托可以像廣播一樣將影響信息“傳播”到四面八方。多播委托類擁有一個方法調用列表,調用委托時,它就會逐一調用該列表中的方法,從而實現多重影響。比較簡單,暫不舉例說明了。

 

本文暫且告一段落,如果想查看更多文章,請關注“小項目筆記”公眾號;

如有疑問:可加入QQ群號:732982683

 


免責聲明!

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



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