筆記來自金旭亮的電子教案“委託與事件”中的委託部分和他的書《.NET4.0物件導向編程漫談 基礎篇》
委託是.NET中事件、非同步呼叫和多線程開發的技術基礎
委託可以看成是方法的容器(最典型的是控制項事件中的+=和-=符號),將某種具體的方法裝入後,可以把它當成方法一樣調用。
C#編譯器對委託的處理方法:
public delegate int MathOptDelegate(int val1,int val2);
上面的委託被編譯器編譯為:
public class MathOptDelegate:System.MulticastDelegate
{
public MathOptDelegate(Object target,Int32 methodPtr);
public void virtual Invoke(Int32 val1,Int32 val2);
public virtual IAsyncResult BeginInvoke(
Int32 val1,Int32 val2,ASyncCallback,Object object);
public virtual void EndInvoke(IAsyncResult result);
}
MulticastDelegate表示多路廣播委託,有一個參數為Object和Int32的建構函式,3個虛方法
一個簡單的委託例子:
public class MathOpt
{
public int Add(int arg1,int arg2)
{
return arg1+arg2;
}
}
public delegate int MathOptDelegate(int val1,int val2);
void MainFormLoad(object sender, EventArgs e)
{
MathOptDelegate oppDel;
MathOpt obj=new MathOpt();
oppDel=obj.Add;
string str=oppDel(20,12).ToString();
MessageBox.Show(string.Format("20+12={0}",str),"Delegate Demo", MessageBoxButtons.OK);
}
定義一個簽名類型為int func(int val1,int val2)的的委託,依照此委託簽名定義一個函數Add(int,int)
然後執行個體化一個委託即oppDel,然後把這個符合委託簽名的方法賦值給委託,最後通過執行個體化的委託調用此方法,調用方法是oppDel(int ,int),格式只和委託簽名相關,和具體的方法名無關。
每一個委託都確定了一個方法的簽名。大多數情況下,擁有不同簽名的方法不能賦值給同一個委託變數。
下面是一個四則運算運用委託的例子:
定義一個委託:
public delegate double CalculateDelegate(double x,double y);
這個委託決定了運算時到底用哪個運算,完整的代碼如下:
public delegate double CalculateDelegate(double x,double y);
private CalculateDelegate curOpt;
void DoCalculate(CalculateDelegate calMethod)
{
double x,y;
x=int.Parse(textBox1.Text);y=int.Parse(textBox2.Text);
labResult.Text=string.Format("結果:{0}",calMethod(x,y));
}
double Add(double x,double y){return x+y;}
double Subtract(double x,double y){return x-y;}
double Multiplicate(double x,double y){return x*y;}
double Divide(double x,double y){return x/y;}
void RadioButton1CheckedChanged(object sender, EventArgs e)
{
foreach(RadioButton r in groupBox2.Controls)
{
if(r is RadioButton)
{
if(r.Checked==true)
{
int i=groupBox2.Controls.IndexOf(r);
switch(i)
{
case 0:
curOpt=Add;
break;
case 1:
curOpt=Subtract;
break;
case 2:
curOpt=Multiplicate;
break;
case 3:
curOpt=Divide;
break;
}
}
}
}
DoCalculate(curOpt);
}
定義委託變數後,定義一個調用方法,調用方法以委託作為參數,RadioButton的Check屬性變化時,委託變數也隨之發生變化,給委託變數賦值後,調用觸發方法。就是單純的改變委託
利用委託實現多表單通訊的例子:
為了方便給委託變數賦值,把委託變數放在從表單中,具體的代碼:
Program.cs中:
public delegate void ShowInfoDelegate(string info);
主表單中:
void MainFormLoad(object sender,EventArgs e)
{
ChildForm c=new ChildForm();
c.recorder=Record;
c.Show();
}
private void Record(string str)
{
label1.Text=str;
}
從表單代碼:
public ShowInfoDelegate recorder;
private int counter;
void Button1Click(object sender, EventArgs e)
{
counter++;
if(recorder!=null)
recorder(counter.ToString());
}
載入子表單時,把主表單中的一個顯示記錄的方法賦值給了從表單中的委託變數,然後由從表單中的Button觸發
冰山一角,還有泛型委派、匿名方法與Lambda運算式、回調,僅是這本書裡面的,還有一節“深入探索委託技術內幕”,由於技術和理解能力不到家,先不吸收了。