与委托的签名(由返回类型和参数组成)匹配的任何方法都可以分配给该委托。这样就可以通过编程方式来更改方法调用,还可以向现有类中插入新代码。只要知道委托的签名,便可以分配自己的委托方法。
将方法作为参数进行引用的能力使委托成为定义回调方法的理想选择。例如,可以向排序算法传递对比较两个对象的方法的引用。分离比较代码使得可以采用更通用的方式编写算法。
委托具有以下特点:
-
委托类似于 C++ 函数指针,但它是类型安全的。
-
委托允许将方法作为参数进行传递。
-
委托可用于定义回调方法。
-
委托可以链接在一起;例如,可以对一个事件调用多个方法。
-
方法不需要与委托签名精确匹配。有关更多信息,请参见协变和逆变。
-
C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。
using System; using System.Collections.Generic; using System.Text; namespace TestWindowsApplication { public class Maths { public int add(int x, int y) { return x + y; } public int minus(int x, int y) { return x - y; } }}
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Text; 7 using System.Windows.Forms; 8 9 namespace TestWindowsApplication 10 { 11 public partial class Form1 : Form 12 { 13 //定义一个委托 14 public delegate int MyHandler(int x, int y); 15 16 public Form1() 17 { 18 InitializeComponent(); 19 } 20 21 private void Form1_Load(object sender, EventArgs e) 22 { 23 24 } 25 26 private void button1_Click(object sender, EventArgs e) 27 { 28 int x = this.textBox1.Text == "" ? 0 : int.Parse(this.textBox1.Text); 29 int y = this.textBox2.Text == "" ? 0 : int.Parse(this.textBox2.Text); 30 31 Maths maths = new Maths(); 32 //绑定到maths实例的add方法 33 MyHandler addhandler = new MyHandler(maths.add); 34 //调用 35 int addResult = addhandler(x, y); 36 MessageBox.Show(string.Format("{0} values: {1}", addhandler.Method.Name, addResult)); 37 } 38 39 private void button2_Click(object sender, EventArgs e) 40 { 41 int x = this.textBox1.Text == "" ? 0 : int.Parse(this.textBox1.Text); 42 int y = this.textBox2.Text == "" ? 0 : int.Parse(this.textBox2.Text); 43 44 StringBuilder sb = new StringBuilder(); 45 Maths maths = new Maths(); 46 47 MyHandler all = null; 48 //绑定到maths实例的add方法 49 MyHandler add = new MyHandler(maths.add); 50 //绑定到maths实例的minus方法 51 MyHandler minus = new MyHandler(maths.minus); 52 53 //链接 54 all += add; 55 all += minus; 56 57 //定义传入参数 58 object[] param ={ x, y }; 59 60 //获取目标委托数组 61 Delegate[] delegates = all.GetInvocationList(); 62 foreach (Delegate dg in delegates) 63 { 64 try 65 { 66 //动态调用当前委托所表示的方法 67 int addResult = (int)dg.DynamicInvoke(param); 68 sb.AppendFormat("{0} values: {1}\n", dg.Method.Name, addResult); 69 } 70 catch (Exception et) 71 { 72 MessageBox.Show(et.Message); 73 } 74 } 75 76 MessageBox.Show(sb.ToString()); 77 } 78 79 private void button3_Click(object sender, EventArgs e) 80 { 81 int x = this.textBox1.Text == "" ? 0 : int.Parse(this.textBox1.Text); 82 int y = this.textBox2.Text == "" ? 0 : int.Parse(this.textBox2.Text); 83 84 Maths maths = new Maths(); 85 //绑定到maths实例的add方法 86 MyHandler addhandler = new MyHandler(maths.add); 87 88 //异步调用开始 89 IAsyncResult ar = addhandler.BeginInvoke(x, y, null, null); 90 91 //异步操作是否完成 92 while (!ar.IsCompleted) 93 { 94 //如果没完成,当前线程阻止时间为10毫秒 95 System.Threading.Thread.Sleep(10); 96 } 97 //异步调用完成,返回结果 98 int addResult = addhandler.EndInvoke(ar); 99100 MessageBox.Show(string.Format("{0} values: {1}", addhandler.Method.Name, addResult));101 }102103 }104}