委託和事件在C#中使用很多,尤其在進行窗體編程時,很多的操作都要透過委託和事件來處理和傳遞。這裡詳細解釋下委託和事件的用法和原因,使我們在寫程式碼時能更明白一些。
委託的使用
事件是一種機制,事件是透過委託實現的,所以看明白了委託,對於事件也就能更好的理解了。先看下面一個小例子。
這是描述不同語言的程式設計師的程式碼:
例如使用C#的程式設計師我們這樣描述,其中programerName參數表示這個程式設計師的姓名。
public void CsharpProgramer(string programerName) { Console.WriteLine(string.Format("{0} 使用C#编程!", programerName)); }
使用Java的,
public void JavaProgramer(string programerName) { Console.WriteLine(string.Format("{0} 使用Java语言编程!")); }
那麼多語言,怎麼區分這是哪個程式設計師呢?使用一個列舉來表示,
public enum ProgramLanguage { CSharp, C, Java }
那麼進行一個完整的描述,代碼如下:
public class ProgramerDescription { //01 public void CsharpProgramer(string programerName) { Console.WriteLine(string.Format("{0} 使用C#编程!", programerName)); } public void CProgramer(string programerName) { Console.WriteLine(string.Format("{0}使用C语言编程!", programerName)); } public void JavaProgramer(string programerName) { Console.WriteLine(string.Format("{0} 使用Java语言编程!")); } //02 public void Description(string programerName, ProgramLanguage type) { switch (type) { case ProgramLanguage.CSharp: CsharpProgramer(programerName); break; case ProgramLanguage.C: CProgramer(programerName); break; case ProgramLanguage.Java: JavaProgramer(programerName); break; default: Console.WriteLine("A kind of new Language that you never heard of."); break; } } } public enum ProgramLanguage { CSharp, C, Java }
調用:
ProgramerDescription pm = new ProgramerDescription(); pm.Description("杨友山", ProgramLanguage.CSharp);
這時,輸出"楊友山使用C#編程!";
這樣就初步完成了一個對程序員描述的簡單實作。這裡的Description方法是透過一個列舉型別來區別不同的語言。這樣它的維護性是比較差的,因為還有很多程式語言(C++,php,等),如果想加一種語言就要增加一個對應的方法,然後就要修改ProgramLanguage這個枚舉型別。增加方法對原程序影響不大,因為可以用分部類別來實現,而修改枚舉就不合適了,這也不符合物件導向設計思想的開放封閉原則。
那麼在Description方法中怎麼處理呢,也就是不用枚舉了,Description方法如何來區分該調用哪個方法(CsharpProgramer,CProgramer,JavaProgramer)對程式設計師進行描述。
public void Description(string programerName, 某類型某參數)
{
//呼叫對應的方法
}
這裡的某類型就是要用它來區別哪個方法的類型,換句話說,最好就是在這裡我直接把我想要呼叫的方法當作參數傳進去。例如我要呼叫CProgramer方法來描述C程式設計師,
ProgramerDescription pm = new ProgramerDescription();
ing Description(string programerName, 某類型某參數)的「某類型某參數」該怎麼表示呢?
當然我們就想到C#中的委託delegate了。委託是一種資料結構,它引用靜態方法或引用類別實例及該類別的實例方法。 用委託來完成上述的程式碼:
public class ProgramDescriptionDelegate { //委托,表示方法 public delegate void DescriptionDelegate(string programerName); //01 public void CsharpProgramer(string programerName) { Console.WriteLine(string.Format("{0} 使用C#编程!", programerName)); } public void CProgramer(string programerName) { Console.WriteLine(string.Format("{0}使用C语言编程!", programerName)); } public void JavaProgramer(string programerName) { Console.WriteLine(string.Format("{0} 使用Java语言编程!")); } //02 public void Description(string programerName, DescriptionDelegate description) { description(programerName); } }
ProgramDescriptionDelegate pm = new ProgramDescriptionDelegate(); pm.Description("杨友山", pm.CsharpProgramer);
什麼是委託? MSDN這樣解釋的:委託是一種定義方法簽章的類型,可以與具有相容簽章的任何方法關聯,可以透過委託呼叫方法。委託用於將方法作為參數傳遞給其他方法。時間處理程序就是透過委託呼叫的方法。
public void Description(string programerName, DescriptionDelegate description)。呼叫時,
DescriptionDelegate description傳入的是 pm.CsharpProgramer,也就是此時description=pm.CsharpProgramer。其實我們還可以這樣呼叫:
//方法和委托绑定 ProgramDescriptionDelegate pm = new ProgramDescriptionDelegate(); YYS.CSharpStudy.Window.SDelegate.ProgramDescriptionDelegate.DescriptionDelegate csharpDelegate = pm.CsharpProgramer; YYS.CSharpStudy.Window.SDelegate.ProgramDescriptionDelegate.DescriptionDelegate cdelegate = pm.CProgramer; pm.Description("杨友山", csharpDelegate); pm.Description("D.M.Ritchie", cdelegate);
ProgramDescriptionDelegate pm = new ProgramDescriptionDelegate(); YYS.CSharpStudy.Window.SDelegate.ProgramDescriptionDelegate.DescriptionDelegate pdelegate = null; pdelegate += pm.CsharpProgramer; pdelegate += pm.CProgramer; pm.Description("杨友山", pdelegate);
可以看出委託不光可以將方法當作參數,而且還可以將方法綁定,而起還可以綁定多個。
使用+=綁定方法,取消則使用-=進行取消,上面的呼叫可以修改如下:
ProgramDescriptionDelegate pm = new ProgramDescriptionDelegate(); YYS.CSharpStudy.Window.SDelegate.ProgramDescriptionDelegate.DescriptionDelegate pdelegate = null; pdelegate += pm.CsharpProgramer; pdelegate += pm.CProgramer; pdelegate -= pm.CProgramer; pm.Description("杨友山", pdelegate);