委託和事件在.NET Framework中的套用非常廣泛,然而,較好地理解委託和事件對很多接觸C#時間不長的人來說並不容易。
基本介紹
- 中文名:c#委託
- 外文名:Delegate
- 程式語言:C#
- 作用:方便的引用被委託的方法
- 套用:NET Framework
引言
參數
public void GreetPeople(string name){ // 做某些額外的事情,比如初始化之類,此處略 EnglishGreeting(name);}public void EnglishGreeting(string name){ Console.WriteLine("Morning, " + name);}
public void ChineseGreeting(string name){ Console.WriteLine("早上好, " + name);}
public enum Language{ English, Chinese}public void GreetPeople(string name, Language lang){ //做某些額外的事情,比如初始化之類,此處略 switch(lang) { case Language.English: EnglishGreeting(name); break; case Language.Chinese: ChineseGreeting(name); break; }}
public void GreetPeople(string name, *** MakeGreeting){ MakeGreeting(name);}
public void EnglishGreeting(string name)public void ChineseGreeting(string name)
public void GreetPeople(string name, GreetingDelegate MakeGreeting){ MakeGreeting(name);}
using System;using System.Collections.Generic;using System.Text;namespace Delegate{ //定義委託,它定義了可以代表的方法的類型 public delegate void GreetingDelegate(string name); class Program { private static void EnglishGreeting(string name) { Console.WriteLine("Morning, " + name); } private static void ChineseGreeting(string name) { Console.WriteLine("早上好, " + name); } //注意此方法,它接受一個GreetingDelegate類型的參數,該參數是返回值為空,參數為string類型的方法 private static void GreetPeople(string name, GreetingDelegate MakeGreeting) { MakeGreeting(name); } static void Main(string[] args) { GreetPeople("Jimmy Zhang", EnglishGreeting); GreetPeople("張子陽", ChineseGreeting); Console.ReadKey(); } }}
委託
static void Main(string[] args) {string name1, name2;name1 = "Jimmy Zhang";name2 = "張子陽";GreetPeople(name1, EnglishGreeting);GreetPeople(name2, ChineseGreeting);Console.ReadKey();}
static void Main(string[] args) {GreetingDelegate delegate1, delegate2;delegate1 = EnglishGreeting;delegate2 = ChineseGreeting;GreetPeople("Jimmy Zhang", delegate1);GreetPeople("張子陽", delegate2);Console.ReadKey();}
static void Main(string[] args) {GreetingDelegate delegate1;delegate1 = EnglishGreeting; // 先給委託類型的變數賦值delegate1 += ChineseGreeting; // 給此委託變數再綁定一個方法// 將先後調用 EnglishGreeting 與 ChineseGreeting 方法GreetPeople("Jimmy Zhang", delegate1);Console.ReadKey();}
static void Main(string[] args) {GreetingDelegate delegate1;delegate1 = EnglishGreeting; // 先給委託類型的變數賦值delegate1 += ChineseGreeting; // 給此委託變數再綁定一個方法// 將先後調用 EnglishGreeting 與 ChineseGreeting 方法delegate1 ("Jimmy Zhang");Console.ReadKey();}
static void Main(string[] args) {GreetingDelegate delegate1 = new GreetingDelegate(EnglishGreeting);delegate1 += ChineseGreeting; // 給此委託變數再綁定一個方法// 將先後調用 EnglishGreeting 與 ChineseGreeting 方法GreetPeople("Jimmy Zhang", delegate1);Console.WriteLine();delegate1 -= EnglishGreeting; //取消對EnglishGreeting方法的綁定// 將僅調用 ChineseGreetingGreetPeople("張子陽", delegate1);Console.ReadKey();}
由來
namespace Delegate {//定義委託,它定義了可以代表的方法的類型public delegate void GreetingDelegate(string name);//新建的GreetingManager類public class GreetingManager{public void GreetPeople(string name, GreetingDelegate MakeGreeting) {MakeGreeting(name);}}class Program {private static void EnglishGreeting(string name) {Console.WriteLine("Morning, " + name);}private static void ChineseGreeting(string name) {Console.WriteLine("早上好, " + name);}static void Main(string[] args) {// ... ...}}}
static void Main(string[] args) {GreetingManager gm = new GreetingManager();gm.GreetPeople("Jimmy Zhang", EnglishGreeting);gm.GreetPeople("張子陽", ChineseGreeting);}
static void Main(string[] args) {GreetingManager gm = new GreetingManager();GreetingDelegate delegate1;delegate1 = EnglishGreeting;delegate1 += ChineseGreeting;gm.GreetPeople("Jimmy Zhang", delegate1);}
public class GreetingManager{//在GreetingManager類的內部聲明delegate1變數public GreetingDelegate delegate1;public void GreetPeople(string name, GreetingDelegate MakeGreeting) {MakeGreeting(name);}}
static void Main(string[] args) {GreetingManager gm = new GreetingManager();gm.delegate1 = EnglishGreeting;gm.delegate1 += ChineseGreeting;gm.GreetPeople("Jimmy Zhang", gm.delegate1);}
public class GreetingManager{//在GreetingManager類的內部聲明delegate1變數public GreetingDelegate delegate1;public void GreetPeople(string name) {if(delegate1!=null){ //如果有方法註冊委託變數delegate1(name); //通過委託調用方法}}}
static void Main(string[] args) {GreetingManager gm = new GreetingManager();gm.delegate1 = EnglishGreeting;gm.delegate1 += ChineseGreeting;gm.GreetPeople("Jimmy Zhang"); //注意,這次不需要再傳遞 delegate1變數}
public class GreetingManager{//這一次我們在這裡聲明一個事件public event GreetingDelegate MakeGreet;public void GreetPeople(string name) {MakeGreet(name);}}
static void Main(string[] args) {GreetingManager gm = new GreetingManager();gm.MakeGreet = EnglishGreeting; // 編譯錯誤1gm.MakeGreet += ChineseGreeting;gm.GreetPeople("Jimmy Zhang");}
編譯代碼
private GreetingDelegate MakeGreet; //對事件的聲明 實際是 聲明一個私有的委託變數[MethodImpl(MethodImplOptions.Synchronized)]public void add_MakeGreet(GreetingDelegate value){this.MakeGreet = (GreetingDelegate) Delegate.Combine(this.MakeGreet, value);}[MethodImpl(MethodImplOptions.Synchronized)]public void remove_MakeGreet(GreetingDelegate value){this.MakeGreet = (GreetingDelegate) Delegate.Remove(this.MakeGreet, value);}
private GreetingDelegate MakeGreet; //對事件的聲明 實際是 聲明一個私有的委託變數 [MethodImpl(MethodImplOptions.Synchronized)]public void add_MakeGreet(GreetingDelegate value){ this.MakeGreet = (GreetingDelegate) Delegate.Combine(this.MakeGreet, value);}[MethodImpl(MethodImplOptions.Synchronized)]public void remove_MakeGreet(GreetingDelegate value){ this.MakeGreet = (GreetingDelegate) Delegate.Remove(this.MakeGreet, value);}
public delegate void GreetingDelegate(string name);當編譯器遇到這段代碼的時候,會生成下面這樣一個完整的類:public sealed class GreetingDelegate:System.MulticastDelegate{public GreetingDelegate(object @object, IntPtr method);public virtual IAsyncResult BeginInvoke(string name, AsyncCallback callback, object @object);public virtual void EndInvoke(IAsyncResult result);public virtual void Invoke(string name);}
設計模式
using System;using System.Collections.Generic;using System.Text;namespace Delegate { // 熱水器 public class Heater { private int temperature; public delegate void BoilHandler(int param); //聲明委託 public event BoilHandler BoilEvent; //聲明事件 // 燒水 public void BoilWater() { for (int i = 0; i <= 100; i++) { temperature = i; if (temperature > 95) { if (BoilEvent != null) { //如果有對象註冊 BoilEvent(temperature); //調用所有註冊對象的方法 } } } }}// 警報器public class Alarm { public void MakeAlert(int param) { Console.WriteLine("Alarm:嘀嘀嘀,水已經 {0} 度了:", param); }}// 顯示器public class Display { public static void ShowMsg(int param) { //靜態方法 Console.WriteLine("Display:水快燒開了,當前溫度:{0}度。", param); }}class Program { static void Main() { Heater heater = new Heater(); Alarm alarm = new Alarm(); heater.BoilEvent += alarm.MakeAlert; //註冊方法 heater.BoilEvent += (new Alarm()).MakeAlert; //給匿名對象註冊方法 heater.BoilEvent += Display.ShowMsg; //註冊靜態方法 heater.BoilWater(); //燒水,會自動調用註冊過對象的方法 } }}
範例說明
namespace Delegate {class Heater {private int temperature; // 水溫// 燒水public void BoilWater() {for (int i = 0; i <= 100; i++) {temperature = i;if (temperature > 95) {MakeAlert(temperature);ShowMsg(temperature);}}}// 發出語音警報private void MakeAlert(int param) {Console.WriteLine("Alarm:嘀嘀嘀,水已經 {0} 度了:" , param);}// 顯示水溫private void ShowMsg(int param) {Console.WriteLine("Display:水快開了,當前溫度:{0}度。" , param);}}class Program {static void Main() {Heater ht = new Heater();ht.BoilWater();}}}
模式簡介
// 熱水器public class Heater {private int temperature;// 燒水private void BoilWater() {for (int i = 0; i <= 100; i++) {temperature = i;}}}// 警報器public class Alarm{private void MakeAlert(int param) {Console.WriteLine("Alarm:嘀嘀嘀,水已經 {0} 度了:" , param);}}// 顯示器public class Display{private void ShowMsg(int param) {Console.WriteLine("Display:水已燒開,當前溫度:{0}度。" , param);}}
委託事件
using System;using System.Collections.Generic;using System.Text;namespace Delegate {// 熱水器public class Heater {private int temperature;public string type = "RealFire 001"; // 添加型號作為演示public string area = "China Xi'an"; // 添加產地作為演示//聲明委託public delegate void BoiledEventHandler(Object sender, BoiledEventArgs e);public event BoiledEventHandler Boiled; //聲明事件// 定義BoiledEventArgs類,傳遞給Observer所感興趣的信息//繼承EventArgspublic class BoiledEventArgs : EventArgs {public readonly int temperature;//public BoiledEventArgs(int temperature) {this.temperature = temperature;}}
// 可以供繼承自 Heater 的類重寫,以便繼承類拒絕其他對象對它的監視protected virtual void OnBoiled(BoiledEventArgs e) {if (Boiled != null) { // 如果有對象註冊Boiled(this, e); // 調用所有註冊對象的方法}}// 燒水。public void BoilWater() {for (int i = 0; i <= 100; i++) {temperature = i;if (temperature > 95) {//建立BoiledEventArgs 對象。BoiledEventArgs e = new BoiledEventArgs(temperature);OnBoiled(e); // 調用 OnBoiled方法}}}}// 警報器public class Alarm {public void MakeAlert(Object sender, Heater.BoiledEventArgs e) {Heater heater = (Heater)sender; //這裡是不是很熟悉呢?//訪問 sender 中的公共欄位Console.WriteLine("Alarm:{0} - {1}: ", heater.area, heater.type);Console.WriteLine("Alarm: 嘀嘀嘀,水已經 {0} 度了:", e.temperature);Console.WriteLine();}}// 顯示器public class Display {public static void ShowMsg(Object sender, Heater.BoiledEventArgs e) { //靜態方法Heater heater = (Heater)sender;Console.WriteLine("Display:{0} - {1}: ", heater.area, heater.type);Console.WriteLine("Display:水快燒開了,當前溫度:{0}度。", e.temperature);Console.WriteLine();}}class Program {static void Main() {Heater heater = new Heater();Alarm alarm = new Alarm();heater.Boiled += alarm.MakeAlert; //註冊方法heater.Boiled += (new Alarm()).MakeAlert; //給匿名對象註冊方法heater.Boiled += new Heater.BoiledEventHandler(alarm.MakeAlert); //也可以這么註冊heater.Boiled += Display.ShowMsg; //註冊靜態方法heater.BoilWater(); //燒水,會自動調用註冊過對象的方法}}}