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);
}
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),格式只和委托签名相关,和具体的方法名无关。
每一个委托都确定了一个方法的签名。大多数情况下,拥有不同签名的方法不能赋值给同一个委托变量。

下面是一个四则运算运用委托的例子:
image
定义一个委托:
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属性变化时,委托变量也随之发生变化,给委托变量赋值后,调用触发方法。就是单纯的改变委托

利用委托实现多窗体通信的例子:
image
为了方便给委托变量赋值,把委托变量放在从窗体中,具体的代码:
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表达式、回调,仅是这本书里面的,还有一节“深入探索委托技术内幕”,由于技术和理解能力不到家,先不吸收了。 

posted @ 2011-06-26 21:23  L Cooper  阅读(624)  评论(3编辑  收藏  举报