- 委托实际就是C语言的函数指针。
- 2个必须条件:方法类型和参数类型及数量必须一致(类型和数量)。
- 局部声明的方法实际是有地址的。
- 委托是全局的,
- 所以绑定方法地址后,任何地方呼叫委托,实际就是呼叫你绑定的方法。
- C语言里有野指针的情况,C#做了优化,不允许null地址和左右值类型不匹配不能绑定。
无返回值: Control 控件父类
- namespace System
- {
- [__DynamicallyInvokable]
- public delegate void Action<in T>(T obj);
- }
- // 系统默认定义了全局变量的委托,名字叫 Action
- // 方法原型,方法参数
- textBox1.Invoke(new Action<string>(str => { textBox1.Text = str; }),"str是参数的名字");
字符串会代入str

这是3个参数的无返回值方法
有返回值:
- public object Invoke(Delegate method)
- {
- return Invoke(method, null);
- }
无参有返回
- namespace System
- {
- [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
- [__DynamicallyInvokable]
- public delegate TResult Func<in T, out TResult>(T arg);
- }
< >内是类型占位符, 最后一个是返回值的类型。 只有1个参数时,括号可不写,直接写参数名字,比如 x
textBox1.Invoke(new Func<string, string>(x => textBox1.Text = x.ToString()),"x是参数名字");
第2个string是返回值的类型。
问题出在哪:在类A内,新建类B,类A是可以调用B的属性和方法,但是B的方法体内,不能调用A的方法。
切入点:在学C语言的时候,如果函数体在main方法后面,那main的前面必须写函数声明。
C#也是如此。类A 内 using引用了 类B 命名空间,那这个命名空间就相当于全局变量区。(A和B都访问的到) 在类B命名空间下 delegate方法声明。
主窗体是可以访问子窗体属性的,所以把 delegate定义成子窗体的属性(中介)。子窗体当然可以使用自己的属性。子窗体的方法内调用自己的属性。
主窗体把自己的方法绑定给子窗体的属性(中介)。这样子窗体调用的时候间接的调用主窗体的方法。
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
-
- ///
- /// qq750273008,委托测试
- ///
- namespace delegateTest
- {
- //【1】第1步:声明委托(公共区)
- public delegate void WT子呼叫(string str, string str2);//子窗体用
-
- public delegate void WT主广播(string str ,string str2);// 主窗使用 (加载所有子窗的方法)方便统一管理
-
- //主窗体
- public partial class Form1 : Form
- {
- #region 全局变量
-
- UInt16 fromNum = 1;//子窗体编号
- WT主广播 wt主广播;//主窗的.属性(用于加载子窗的方法)
- private List
-
- #endregion
-
- #region 窗体构造
- public Form1()
- {
- InitializeComponent();
- }
- #endregion
-
- #region 钮_创建子窗体
- private void btn1_创建子窗体(object sender, EventArgs e)
- {//创建子窗体
-
- for (int i = 0; i < 3; i++)//每次创建3个窗口
- {
- Form2 form子窗 = new Form2("子窗体", $"子窗体:{fromNum++}");
- form子窗.Show();
-
- //===========================
- //【4】第4步:将委托变量和具体方法关联(使用=和+=是一样的效果)
- form子窗.wt子呼叫 += x显示子消息;//子窗体 呼叫 主窗体
-
- //===========================
- this.wt主广播 += form子窗.父消息;//调用子窗体方法
-
- forms.Add(form子窗);//加入到集合,方便控制
- }
- }
- #endregion
-
- #region 显示消息
-
- //【2】第2步:根据委托编写具体方法
- private void x显示子消息(string str, string str2)
- {
- string str3 = ("来自" + str + " 的消息:" + str2 + "\r\n");
- textBox1.AppendText(str3);
- }
- #endregion
- #region 广播
- private void btn4_广播(object sender, EventArgs e)
- {
- try
- {
- wt主广播("主广播:", textBox2.Text);//wt广播A
- }
- catch (Exception ex)
- {
-
- MessageBox.Show("没有子窗体,无法发送", "失败");
- MessageBox.Show(ex.Message);
- // throw;
- }
-
- }
- #endregion
-
- #region 清空
- private void btn2_清空(object sender, EventArgs e)
- {
- textBox1.Text = string.Empty;
- }
- #endregion
-
- #region 关闭子窗体
- private void btn3_关闭子窗体(object sender, EventArgs e)
- {//关闭窗口
- foreach (var item in forms)
- {
- item.Close();
- }
- fromNum = 1;//子窗体编号复位
- }
- #endregion
-
- }
- }
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
-
- namespace delegateTest
- {
- //子窗体
- public partial class Form2 : Form
- {
- //【3】第3步:声明委托
- public WT子呼叫 wt子呼叫;// 属性
-
- public Form2(string str, string str2)
- {
- InitializeComponent();
-
- this.Text = str2;
-
- }
-
- public void 父消息(string str,string str2)
- {
- textBox2_接收框.Text = str + str2;
- }
-
- private void btn1发送消息(object sender, EventArgs e)//触发按键
- {
- //【1】第5步:使用委托变量来调用所关联的方法
- //wt("测试", "123");
- wt子呼叫(this.Text.ToString(), textBox1_发送框.Text.ToString()); // 子窗编号 + 内容
- }
- }
- }
