C#委托(1)
笔记来自金旭亮的电子教案“委托与事件”中的委托部分和他的书《.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);
}
一个简单的委托例子:
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());
}
冰山一角,还有泛型委托、匿名方法与Lambda表达式、回调,仅是这本书里面的,还有一节“深入探索委托技术内幕”,由于技术和理解能力不到家,先不吸收了。