代码改变世界

C# note 06——delegate 和 event

2015-04-20 23:11  yinglang  阅读(146)  评论(0编辑  收藏  举报

1. Delegate类似于于c++中的函数指针,在C#中定义为一个类

声明定义时,有些像类:

delegate int MyDelegate(char c);

实例化:(注意函数不要加括号,要的不是函数调用,而是函数地址)

MyDelegate myfuncs = new MyDelegate(MyClass.testFunc);

MyDelegate myfuncs = MyClass.testFunc;

不支持无参数的构造函数。

MyDelegate myfuncs = new MyDelegate();

将多个同类型函数绑到同一个delegate中,可以将一个函数加多次:

myfuncs += MyClass.testFunc;

也可以卸下函数

myfuncs -= MyClass.testFunc;

加入的函数会按加入顺序逐个执行。

private void button1_Click(object sender, EventArgs e)

        {

            MyDelegate mydelegate = new MyDelegate(changeByuttonText);

            mydelegate += changeByuttonText;

            TTT t = new TTT();

            mydelegate(t);

        }

 

        public delegate void MyDelegate(TTT t);

        void changeByuttonText(TTT t)

        {

            t.num += 1;

            myButton.Text = "changed" + (t.num);

        }

 

        public class TTT

        {

            public int num = 1;

        }

上面程序,每次点击事件触发时,t.num加2,当然这是对于引用传递的变量,如果是值传递的变量做参数,则只会加1

如果只是声明,而没有赋值如,MyDelegate myfunc;则myfunc不能使用“+=”符号(类似空指针)

完整代码如下:

总结

委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

2. event 与 delegate的使用

以窗体程序中的button控件为例:

a) 新建一个winForm 程序,从工具箱中将一个button移入窗体,这时在Form1.cs程序中多了一个函数。

        private void button1_Click(object sender, EventArgs e)

        {

        }

在这个函数里可以声明这个button的点击事件。但是.net是怎么调用这个函数的呢?

b) 选中button1_Click右键【查看所有引用】,其中有一个是来自Form1.Designer.cs的引用,点开发现这句代码

this.button1.Click += new System.EventHandler(this.button1_Click);

(注:这句代码在类Form1中的函数private void InitializeComponent()中,在Form1.cs中声明的是public partial class Form1 : Form继承自Form类的Form1类的一部分(partial),它的构造函数中的InitializeComponent() 的定义正是在Form1.Desinger.cs中)

这句代码的语法很像delegate的“+=”挂接运算。

c) 选中Click,右键【转到定义】转到命名空间System.Windows.Forms的Control类中,在这里我们发现

public event EventHandler Click;

Click正是一个event,是一个delegate(EventHandler),

d) 在这个类里往下找,有许多与点击事件有关的函数,其中有一个

protected virtual void OnClick(EventArgs e);

  很可能就是在这一步调用的Click,即我们自己定义的button1_Click()函数。

e) 为了验证,自己建一个MyButton类,继承Button。重写OnClick函数

public class MyButton : Button

    {

        public delegate void ClickEventHandler(object sender, EventArgs e);

        public event ClickEventHandler ClickEvent;

 

        protected override void OnClick(EventArgs a){

            if (ClickEvent != null)

            {

                this.Text = "MyButton:我被单击了\n";

                ClickEvent(this, null);

            }

        }

    }

在Form1类中进行修改如下

public Form1()

{

            InitializeComponent();

            myButton.Location = new Point(10,10);

            myButton.Size =  new System.Drawing.Size(160,60);

            myButton.Text = "hello";

            this.Controls.Add(myButton);

            myButton.ClickEvent += new MyButton.ClickEventHandler(OnClickEvent);

        }

        void OnClickEvent(object sender,EventArgs e)

        {

            myButton.Text +=("MyForm:我知道你被单击了");

}

运行结果如下:

 

3. event 和 delegate的区别

a) delegate和类是一个级别的,可以直接写命名空间下,不用寄存在类中;

event和函数,property是一个级别,必须写在类中。

b) event 要声明必先要有一个delegate(EventHandler)

delegate int MyDelegate();

event MyDelegate MyEvntHandler;