委托:就是一个能存放符合某种格式(方法签名)的方法指针的容器。
委托的作用:1.能将方法作为参数和返回值传递; 2.调用一个委托,执行N个方法(多播委托)。
/* 1.声明委托的本质: * 1.1委托编译后 生成一个 同名类(DGTest) * 1.2继承关系: DGTest -> MulticastDelegate -> Delegate */ public delegate void DGTest(); private void btnTest_Click(object sender, EventArgs e) { //语法糖:在C#中有很多 简洁语法,实质是由编译器 在编译时 转成 完整语法,那么这种 简洁语法叫做语法糖 //2.创建委托对象 DGTest dg = Test;//new DGTest(this.Test); /*3.为委托追加方法的本质: * 是为 被追加的方法创建一个新的委托对象,并将 方法 指针存入对象的 父类的父类(Delegate)的 IntPtr 变量中 * 然后再将 新创建的委托 添加到 当前委托对象(dg)的 数组中 */ dg += Test2;//编译后:(DGTest) Delegate.Combine(dg, new DGTest(this.Test2)); dg += Test3;//编译后:(DGTest) Delegate.Combine(dg, new DGTest(this.Test3)); dg -= Test3;//编译后:(DGTest) Delegate.Remove(dg, new DGTest(this.Test3)); /*4.调用委托,其实就是通过调用委托对象里的Invoke方法 遍历 委托内部的数组,然后依次调用 数组中的 方法 */ dg();//编译后:dg.Invoke(); /* 委托的作用: * 1.将方法做为参数 * 2.将方法作为返回值 */ } void Test() { MessageBox.Show("Test"); } void Test2() { MessageBox.Show("Test2"); } void Test3() { MessageBox.Show("Test3"); } #region 1.0 委托当参数 private void btnPara_Click(object sender, EventArgs e) { InvokeTest(Test); InvokeTest(Test2); InvokeTest(Test3); } /// <summary> /// 委托当参数使用: 调用 3个 Test 方法 中的某一个 /// </summary> /// <param name="strType"></param> public void InvokeTest(DGTest dgTest) { dgTest(); } #endregion #region 2.0 委托当返回值 private void btnReturn_Click(object sender, EventArgs e) { DGTest dg = InvokeTest("1"); dg(); } /// <summary> /// 委托当返回值 /// </summary> /// <param name="strType"></param> /// <returns></returns> public DGTest InvokeTest(string strType) { switch (strType) { case "1": return Test; case "2": return Test2; default: return Test3; } } #endregion #region 3.0 使用泛型方法 加 泛型委托 完成 通用版的 Max方法 /// <summary> /// 使用泛型方法 加 泛型委托 完成 通用版的 Max方法 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnFindMax_Click(object sender, EventArgs e) { int[] arrInt = new int[5] { 1, 2, 5, 6, 3 }; //int Max = MaxInt(arrInt); int max = MaxValue<int>(arrInt, (x, y) => x - y); string[] arrStr = new string[] { "a", "c", "b" }; string maxLengthStr = MaxValue<string>(arrStr, (x, y) => x.Length - y.Length); Dog[] dogs = new Dog[] { new Dog() { age = 1, name = "小白" }, new Dog() { age = 0, name = "小白2" }, new Dog() { age = 5, name = "小白3" } }; Dog maxAgeDog = MaxValue<Dog>(dogs, (x, y) => x.age - y.age); } int MaxInt(int[] arr) { int maxInt = arr[0]; for (int i = 1; i < arr.Length; i++) { if (maxInt < arr[i]) { maxInt = arr[i]; } } return maxInt; } T MaxValue<T>(T[] arr, Comparison<T> func) { T maxInt = arr[0]; for (int i = 1; i < arr.Length; i++) { //使用委托来 完成元素 大小的比较过程! if (func(maxInt, arr[i]) < 0) { maxInt = arr[i]; } } return maxInt; } #endregion
public delegate void DGMyClick(DateTime time); //定义委托 /// <summary> /// 三击按钮类 - 用户点击三次后 执行用户的 方法 /// </summary> public class MyTripleButton:System.Windows.Forms.Button { Timer time = new Timer(); public MyTripleButton() { base.Click += MyTripleButton_Click; //为父类的 单击事件 注册一个方法(就是 将一个 方法 存入 Click 属性中) time.Interval = 1000; time.Tick += time_Tick; } int clickTimes = 0; //定义一个 用来保存 用户方法的委托对象 /*使用 事件event封装 委托变量,编译后: * 1.会把被修饰的委托变量私有化(private) * 2.会生成一个 与 委托变量 同名的 事件语法,内部包含 add 和 remove方法 * add 和 remove方法内部都是操作 私有的委托变量 * 3.当外部访问 委托变量时,实际上访问的是 同名的事件语法,并使用 += 和 -= 为封装的 私有委托变量 增删方法 */ public event DGMyClick dgMyClick; void time_Tick(object sender, EventArgs e) { clickTimes = 0; } //每当被点击的时候,此方法会被调用 void MyTripleButton_Click(object sender, EventArgs e) { //如果点击次数没达到3次 if (clickTimes < 2) { //如果是第一次点击 则启动计时器 if (clickTimes == 0) { time.Start(); } //点击次数++ clickTimes++; } else//点击三次后 { //1.执行用户的 方法 if (dgMyClick != null) dgMyClick(DateTime.Now); //2.清空点击次数 clickTimes = 0; //3.重启计时器 time.Stop(); } } } public Form1() { InitializeComponent(); //1.创建三击按钮对象 MyTripleButton myBtn = new MyTripleButton(); //2.利用一个事件机制 为 按钮里的委托对象 注册一个 方法(或 移除一个方法) myBtn.dgMyClick += ClickSelf; //3.注意:因为使用了事件机制 封装了 按钮里的委托对象,所以不能 直接 赋值 和 调用委托了 //myBtn.dgMyClick = null; //myBtn.dgMyClick(); this.Controls.Add(myBtn); } void ClickSelf(DateTime time) { MessageBox.Show("三击了~~~~~~~~~~~~~!加分!"); } 委托和事件的区别:委托时类,事件是用来封装“属性封装”的机制
就是一个能存放符合某种格就是一个能存放符合某种格式(方法签名)的方法的指针的容器式(方法签名)的方法的指针的容
就是一个能存放符合某种格式(方法签名)的方法的指针的容器
原文:http://blog.csdn.net/ankeyuan/article/details/21887421