今天在msdn上看了下委托,简单来说就是一个函数指针,形式如下:
public delegate void DelegateFunc(string message);
DelegateFunc就相当于一个函数指针,可以指向带一个或多个字符串参数无返回值的函数。例如有如下函数:
public void Test1(string str){//body}
则可以将委托实例化
public DelegateFunc df1=Test1;
可以看到这里委托DelegateFunc也是一种数据类型,他产生的对象是由函数名赋值的,这与函数指针是相同的概念。
调用的方式很简单
df1("First time delegate");
也就相当于
Test1("First time delegate");
如果存在另外两个函数
public TestClass
{
public void Test2(string str){//body}
public void Test3(string str){//body}
}
则可以声明两个委托的对象
DelegateFunc df2=Test2;
DelegateFunc df3=Test3;
神奇的是,还可以允许以下的形式存在
df1 +=df2+df3;
df1-=df3;
当执行完+=语句后,df1指向三个函数。当调用df1时,这三个函数将依次被执行。-=语句不言而喻了。
想想用Delphi的钩子时经常用到回调函数,也是这种东西,当时着实被那位大忽悠同学忽悠了一通!!!能做的不如能说的啊!!!
下面以实例看看这个东西有什么意义。
看到csdn某个帖子的时候联想到这样一个问题,首先显示一个form4窗体,其中有个列表框listbox1和一个按钮button1,当点击按钮的时候显示另外一个窗体form3,里面有一个文本框textbox1和一个按钮button2。当点击button2时,listbox1中将添加textbox1中的文字。下面比较一下两种方式。
方法一:在form4中定义一个用于操作listbox1的公共函数
public void AddList(string str)
{
listBox1.Items.Add(str);
}
然后在form3中调用该函数即可。
这种方法实现起来很简单,但是必须等待form3窗体关闭后,form4窗体才会刷新,listbox1中的数据才会显示,效果不好。
方法二:采用委托。先看一下具体代码
form4:
public partial class Form4 : Form
{
public Form4()
{
InitializeComponent();
}
private void AddList(string str)
{
listBox1.Items.Add(str);
}
private void button1_Click(object sender, EventArgs e)
{
Form3 form3 = new Form3();
form3.form4 = this;
form3.onButtonClick += new Form3.OnButtonClick(AddList);
form3.ShowDialog();
}
}
form3:
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
public Form4 form4;
public delegate void OnButtonClick(string str);
public event OnButtonClick onButtonClick;
private void button2_Click(object sender, EventArgs e)
{
onButtonClick(textBox1.Text);
}
}
这样的实现可以保证form3的添加与form4的显示同步。通过运行过程进一步理解机制:
1、点击form4里的按钮button1时,创建Form3类的实例form3,form3将拥有一个form4对象、和一个委托的实例onButtonClick。
2、通过form3.form4 = this;保证form3和form4的联系唯一而且畅通。这也是多个窗体间调用的一种方式。
3、通过form3.onButtonClick += new Form3.OnButtonClick(AddList);使委托的实例onButtonClick指向了用于操作listbox1的函数,这样以后调用onButtonClick 时就相当于操作listbox1,而且重要的是这个操作有系统自动完成,也就保证了添加与显示的同步。另外需要注意的是,在form4中调用的form3.onButtonClick 必须出现在+=或-=的左侧。
4、当form3窗体显示后,点击button2时,调用委托实例onButtonClick ,即完成listbox1的操作。
这就是一个基本的步骤,我觉得在这里面最重要的就是委托的完成是由系统控制的,类同于回调函数的原理,这一点是委托的优势。另外委托可以指向一系列函数,这也是可以加以利用的地方。