在C#中,委託是一種引用型別的資料型別,允許我們封裝方法的引用。透過使用委託,我們可以將方法作為引數傳遞給其他方法,或者將多個方法組合在一起,從而實現更靈活的程式設計模式。委託類似於函式指標,但提供了型別安全和垃圾回收等現代語言特性。
基本概念
定義委託
定義委託需要指定它所代表的方法的原型,包括返回型別和引數列表。例如:
public delegate int MyDelegate(int a, int b);
這定義了一個名為MyDelegate
的委託,它代表一個接受兩個整數引數並返回一個整數的方法。
建立委託例項
建立委託例項時,可以使用new
關鍵字加上委託型別和要封裝的方法名:
MyDelegate myDelegate = new MyDelegate(AddNumbers);
其中AddNumbers
是一個符合MyDelegate
定義的方法。
呼叫委託
一旦有了委託例項,就可以像呼叫方法一樣呼叫它:
int result = myDelegate(5, 3);
多播委託
委託可以被設計為“多播”的,這意味著它們可以呼叫多個方法。當呼叫多播委託時,所有註冊的方法都會按順序執行:
MyDelegate del1 = new MyDelegate(AddNumbers);
MyDelegate del2 = new MyDelegate(MultiplyNumbers);
MyDelegate combinedDel = del1 + del2;
combinedDel(5, 3); // 先呼叫 AddNumbers, 然後呼叫 MultiplyNumbers
匿名方法和Lambda表示式
從C# 2.0開始,可以使用匿名方法來定義委託:
MyDelegate anonMethod = delegate(int x, int y) { return x + y; };
而在C# 3.0之後,Lambda表示式成為更簡潔的選擇:
MyDelegate lambdaExpr = (int x, int y) => x + y;
事件
在C#中,事件是一種特殊的委託型別,用於封裝訊息的傳送機制,通常用於元件之間或物件之間的通訊。事件是.NET框架中處理非同步操作、UI互動和訊號通知的核心機制。下面詳細介紹事件的概念、定義和使用。
事件的基本概念
事件允許一個類(事件釋出者)向另一個或多個類(事件訂閱者)廣播資訊,而無需直接呼叫接收方的任何方法。這實現了釋出者和訂閱者之間的解耦,使得程式碼更加模組化和可維護。
定義事件
事件基於委託型別定義,通常使用System.EventHandler
或自定義的委託型別。定義事件時,通常在類中宣告一個委託型別的私有欄位,並在此基礎上宣告一個公共的事件屬性。例如:
public class Publisher
{
// 自定義委託型別
public delegate void MyEventHandler(object source, MyEventArgs args);
// 定義事件
private event MyEventHandler myEvent;
// 使用事件屬性暴露事件
public event MyEventHandler MyEvent
{
add { myEvent += value; }
remove { myEvent -= value; }
}
// 觸發事件
public void RaiseEvent()
{
if (myEvent != null)
{
myEvent(this, new MyEventArgs());
}
}
}
在這個例子中,Publisher
類有一個名為MyEvent
的事件,它基於MyEventHandler
委託型別。事件觸發時,RaiseEvent
方法會被呼叫,它會檢查是否有訂閱者,並呼叫所有訂閱者的相應方法。
訂閱和取消訂閱事件
事件可以透過事件處理程式來訂閱。事件處理程式是一個與事件委託型別匹配的方法。訂閱事件時,將事件處理程式新增到事件中;取消訂閱則移除該處理程式。
class Subscriber
{
public void OnMyEvent(object sender, MyEventArgs e)
{
Console.WriteLine("Event triggered.");
}
}
// 在某個地方訂閱事件
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();
publisher.MyEvent += subscriber.OnMyEvent;
// 取消訂閱事件
publisher.MyEvent -= subscriber.OnMyEvent;
使用事件引數
事件經常與事件引數一起使用,這些引數通常封裝了事件發生時的附加資訊。事件引數是透過繼承EventArgs
類來建立的。例如:
public class MyEventArgs : EventArgs
{
public string Message { get; set; }
}
在觸發事件時,可以建立事件引數的例項並傳遞給事件:
public void RaiseEvent()
{
if (myEvent != null)
{
myEvent(this, new MyEventArgs { Message = "Hello, world!" });
}
}