1. 委託概述
“委託”相當於C++中的“函式指標”,委託必須與所要“指向”的函式在“引數”和“返回型別”上保持一致;
// 定義Person類
public class Person {
public string Name = "Rain Man";
public string Speak(string words) {
Console.WriteLine(this.Name + " said: " + words);
return words;
}
}
// 定義委託
public delegate string Dele_Speak(string str);
class Program {
static void Main(string[] args) {
Person p = new Person(); // 例項化Person類
Dele_Speak dp = new Dele_Speak(p.Speak); // 例項化委託:變數dp實際上就是指向p.Speak函式的指標
dp("Welcome to my blog!"); // 輸出:Rain Man said: Welcome to my blog!
Console.ReadLine();
}
}
- 代理“Dele_Speak”與“Speak”方法在引數和返回型別保持一致;
- “Dele_Speak dp = new Dele_Speak(p.Speak)”,實際上就是建立了一個“dp”指標,指向“p.Speak”方法
- “dp("Welcome to my blog!")”,實際上就是“p.Speak("Welcome to my blog!")”
2. 多路廣播
// 定義Person類
public class Person {
public string Speak(string words) {
Console.WriteLine("Speak: " + words);
return "111";
}
public string Say(string words) {
Console.WriteLine("Say: " + words);
return "222";
}
public string Translate(string words) {
Console.WriteLine("Translate: " + words);
return "333";
}
}
// 宣告代理
public delegate string Dele_Str(string str);
class Program {
static void Main(string[] args) {
Person p = new Person(); // 例項化Person類
Dele_Str dp_Speak = new Dele_Str(p.Speak); // 例項化委託指向 p.Speak
Dele_Str dp_Say = new Dele_Str(p.Say); // 例項化委託指向 p.Say
Dele_Str dp_Translate = new Dele_Str(p.Translate); // 例項化委託指向 p.Transpate
// 多路廣播
dp_Speak = dp_Speak + dp_Say;
dp_Speak = dp_Speak + dp_Translate;
string str = dp_Speak("Rain Man");
Console.WriteLine(str); // 輸出:333
Console.ReadLine();
}
}
在Person類中建立了三個函式:Speak、Say、Translate,這三個函式在引數和返回型別上相同,因此可是使用同一個委託(Dele_Str)。
多路委託:使用同一個委託“指向”不同的函式,使這幾個函式可以“計算”,其執行邏輯如下:
執行:
string str = dp_Speak("Rain Man");
輸出:
Speak: Rain Man
Say: Rain Man
Translate: Rain Man
實際上就是執行下述程式碼:
p.Speak("Rain Man");
p.Say("Rain Man");
p.Translate("Rain Man");
返回值:即最後一個函式的返回值
3. 事件代理
有兩個窗體:
- FrmMain:該窗體中有一個按鈕“btnAdd”,當點選此按鈕時通過ShowDialog()方法開啟“FrmUserAdd”窗體
- FrmUserAdd: 該窗體中有一個按鈕“btnOK”,當點選此按鈕時“對外”(對FrmMain窗體)傳送一個“UserAddEvent”事件,通過該事件將“FrmUserAdd”中填寫的“使用者資訊”傳至“FrmMain”窗體中。
3.1 FrmUserAdd窗體:
public partial class FrmUserAdd : Form
{
// 1. 定義事件引數類
public class UserAddEventArgs : EventArgs {
public User AddedUser;
public UserAddEventArgs(User user) {
this.AddedUser = user;
}
}
// 2. 定義委託,並指定引數型別
public delegate void UserAddEventHandler(object sender, UserAddEventArgs e);
// 3. 定義事件,並指定該事件的委託型別
public event UserAddEventHandler UserAddEvent;
private void btnOK_Click(object sender, EventArgs e) {
User user = new User(1, "Rain Man", "");
UserAddEventArgs args = new UserAddEventArgs(user);
if (UserAddEvent != null) {
this.UserAddEvent(this, args);
}
}
}
3.1.1. 自定義事件引數類:UserAddEventArgs
自定義的事件引數類“UserAddEventArgs”必須繼承自“EventArgs”類,在此基礎上新增了public成員“AddedUser”
3.1.2 定義委託:UserAddEventHandler
- 注意該委託的引數型別,第二個引數為“自定義的事件引數”。
- 該委託用於在“FrmMain”窗體中例項化,例項化後繫結事件處理函式“OnUserAdd”。
3.1.3 定義事件變數:UserAddEvent
“UserAddEvent”變數可以理解為“UserAddEventHandler”委託的一個例項化物件,即
public UserAddEventHandler UserAddEvent; // 在該示例中把"event"修飾符去掉也是可以的
3.2 FrmMain窗體
public partial class FrmMain : Form {
// UserAddEvent事件繫結的處理函式
private void OnUserAdd(object sender, FrmUserAdd.UserAddEventArgs e) {
MessageBox.Show(e.AddedUser.username);
}
private void btnAdd_Click(object sender, EventArgs e) {
FrmUserAdd frm = new FrmUserAdd();
FrmUserAdd.UserAddEventHandler dele_fn = new FrmUserAdd.UserAddEventHandler(OnUserAdd);
frm.UserAddEvent += dele_fn;
frm.ShowDialog();
}
}
3.2.1 FrmUserAdd.UserAddEventHandler dele_fn = new FrmUserAdd.UserAddEventHandler(OnUserAdd);
dele_fn為“UserAddEventHandler”的一個例項(指標),它指向事件處理函式“OnUserAdd”
3.2.2 frm.UserAddEvent += dele_fn;
可以看出此處實際就是“多路廣播”,同時也可以看出“UserAddEvent”事件變數實際就是“UserAddEventHandler”委託的一個例項。
3.3 執行邏輯
該示例看似複雜,其實質是將本在“一個窗體”中的實現,拆成了“兩個窗體”。下面將兩個窗體的程式碼合成“一個窗體”
public partial class FrmUserAdd : Form {
// 定義事件引數
public class UserAddEventArgs : EventArgs {
public User AddedUser;
public UserAddEventArgs(User user) {
this.AddedUser = user;
}
}
// 定義委託,並指定引數型別
public delegate void UserAddEventHandler(object sender, UserAddEventArgs e);
// 定義事件,並指定該事件的“委託”
public UserAddEventHandler UserAddEvent;
public event UserAddEventHandler UserAddEvent;
// UserAddEvent事件繫結的處理函式
private void OnUserAdd(object sender, FrmUserAdd.UserAddEventArgs e) {
MessageBox.Show(e.AddedUser.username);
}
private void btnOK_Click(object sender, EventArgs e) {
User user = new User(1, "Rain Man", "");
UserAddEventArgs args = new UserAddEventArgs(user);
FrmUserAdd.UserAddEventHandler dele_fn = new FrmUserAdd.UserAddEventHandler(OnUserAdd);
this.UserAddEvent += dele_fn;
if (UserAddEvent != null)
{
this.UserAddEvent(this, args);
}
}
}