目录

1.委托

2.委托的基本使用

3.为什么要使用委托?

4.委托的实战应用:在多窗体通信中的使用

5.事件(和委托比较)

5.1事件


1.委托

    委托(Delegate)是一个非常重要的概念,但有时候理解起来可能有些抽象。为了通俗易懂地解释委托,我们可以使用日常生活中的一个类比。

    想象一下,你是一家公司的老板,你需要找人来完成一些特定的任务,比如打印文件、发送邮件等。但是,你并不直接管理这些任务的具体执行者,而是通过一个“中介”来安排。这个“中介”知道谁能做什么任务,并在需要的时候将任务分配给相应的人。

    在C#中,委托就像是这个“中介”的角色。它定义了一个方法签名(即方法的返回类型和参数类型),并允许你将任何符合这个签名的方法赋值给它。然后,你可以像调用普通方法一样调用这个委托,而委托则会根据它当前所引用的方法来执行相应的代码。换句话说,委托是一个类型安全的、面向对象的函数指针。它允许你将方法作为参数传递给其他方法,或者将方法赋值给变量,从而实现了方法的动态调用。

2.委托的基本使用

为了更具体地说明,我们可以看一个简单的例子:

 static void Main(string[] args)
 {
     //【3】定义委托变量
     LectureDelegate1 lecture1 = null;
     //【4】将具体方法与委托变量关联
     lecture1 = ChangLecture1;
     lecture1 += ZhangLecture1;
     lecture1 += WangLecture1;

     //【5】使用委托变量
     lecture1();
     //lecture1.Invoke();//委托特有的Invoke();
     //可选择移除方法的关联
     lecture1 -= WangLecture1;
     lecture1();
     LectureDelegate2 lecture2 = CangLecture2;
     Console.WriteLine(lecture2(5, "sad"));

 }
 //【2】根据委托编写方法
 static void ChangLecture1()
 {
     Console.WriteLine("我们正在学习委托技术");
 }
 static void ZhangLecture1()
 {
     Console.WriteLine("我们正在学习C#技术");
 }
 static void WangLecture1()
 {
     Console.WriteLine("我们正在学习.net技术");
 }

 static string CangLecture2(int count,string course)
 {
     return $"李老师主讲的是{course},课时为{count}";
  }
 //【1】定义委托
 public delegate void LectureDelegate1();
 public delegate string LectureDelegate2(int num,string num2);

可知使用委托最重要的步骤为:

  1. 定义委托
  2. 编写要委托的方法
  3. 定义委托变量
  4. 将方法与委托变量关联
  5. 使用委托变量

3.为什么要使用委托?

    使用委托(Delegate)在编程中,特别是在C#这样的面向对象语言中,有几个非常实用的理由。为了通俗易懂地解释这些理由,我们可以借助一些日常生活中的场景。

  • 像中介一样工作

    想象一下你是一位雇主,需要找人来完成某项任务,比如装修房子。但你可能并不认识所有的装修师傅,也不知道哪位最适合你的需求。这时,你可以找一个装修中介,告诉他们你的需求,中介会为你找到合适的装修师傅。

    在C#中,委托就像这个装修中介。它允许你定义一个任务的签名(比如需要哪些参数,返回什么类型),然后你可以将任何符合这个签名的方法“委托”给它。当你需要执行这个任务时,你只需要告诉委托,委托就会为你找到并调用正确的方法。

  • 实现代码的灵活性

    如果你正在编写一个程序,其中某个部分需要在不同的条件下执行不同的代码,那么使用委托可以让代码更加灵活。比如你正在编写一个游戏,其中玩家可以选择不同的角色。每个角色都有自己的攻击方式。你可以为每个角色的攻击方式定义一个方法,并将这些方法委托给同一个变量。这样,在玩家选择角色后,你只需要调用这个委托变量,就可以执行相应角色的攻击方式了。

  • 事件处理

    在C#中,事件处理是通过委托来实现的。比如,在Windows Forms应用程序中,当你点击一个按钮时,就会触发一个点击事件。这个事件是通过一个委托来与事件处理程序(即响应点击事件的方法)关联的。想象一下你正在使用一个遥控器来控制电视。当你按下某个按钮时,遥控器就会发送一个信号给电视。电视接收到信号后,就会执行相应的操作(比如切换频道)。在这里,遥控器发送的信号就像是事件,而电视执行的操作就像是事件处理程序。委托就是用来将信号与操作关联起来的。

  • 多播

    委托还支持多播,这意味着你可以将多个方法关联到同一个委托实例上。当调用这个委托时,它会依次执行所有关联的方法。这就像是你在一个聚会上邀请了多位朋友。当你宣布聚会开始时,每位朋友都会听到并做出反应(比如欢呼、跳舞等)。在这里,你宣布聚会开始就像是调用委托,而每位朋友做出的反应就像是关联到委托上的方法。

4.委托的实战应用:在多窗体通信中的使用

要实现如图所示,每个子窗体发送的消息主窗体都能识别出来并显示。

主窗体代码如下:

 public partial class FrmMain : Form
 {
     public FrmMain()
     {
         InitializeComponent();
     }

     //这个集合主要是为了关闭窗体使用
     private List<Form> frmList = new List<Form>();

     //【1】第2步:根据委托编写具体方法
     private void ReceiveMsg(string msg, string childName)
     {
         this.txtContent.Text = $"来自:{childName}的消息:{msg}\n";
     }


     //创建多个子窗体
     private void btnCreateChildForm_Click(object sender, EventArgs e)
     {
         for(int i = 0; i < 3; i++)
         {
             FrmChild child = new FrmChild($"B子窗体:{i + 1}");
             //【1】第四步:将委托变量与方法关联
             child.passMsg += ReceiveMsg;
             child.Show(this.txtSend);
         }
        
     }

     //清空消息
     private void btnClear_Click(object sender, EventArgs e)
     {
         this.txtContent.Clear();
     }
     //关闭全部
     private void btnCloseAll_Click(object sender, EventArgs e)
     {
         for(int i = 0; i < 3; i++)
         {
             frmList[i].Close();
         }
     }

子窗体代码如下:

//【1】第3步:创建委托变量
public PassMsgDelegate passMsg;

public FrmChild(string childName)
{
    InitializeComponent();
    this.Text = childName;
}

//发送消息
private void btnSend_Click(object sender, EventArgs e)
{
    //【1】第5步:使用委托变量来调用所关联的方法
    passMsg(this.txtSendMsg.Text,this.Text);
}

Main方法如下:

static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new FrmMain());
}

5.事件(和委托比较)

5.1事件

    想象一下,你的公司经常需要组织会议,但每次组织会议的人可能不同。你不希望每次有人需要组织会议时,都直接来找你这个经理,因为这样你会很忙。于是,你设立了一个“事件”(Event),比如“需要组织会议时”。当这个事件发生时,任何注册了这个事件的人(即订阅者)都可以被通知并执行组织会议的任务。

    C#中,事件是基于委托的,但它增加了一层封装。事件只允许外部代码“订阅”或“取消订阅”这个事件,而不能直接“触发”它(除非通过提供的方法)。这样,事件提供了一种发布/订阅模式,让代码更加模块化、解耦。

// 定义一个委托类型
public delegate void OrganizeMeetingHandler();

// 定义一个类,它有一个事件
public class MeetingManager
{
    // 声明事件
    public event OrganizeMeetingHandler MeetingNeeded;

    // 触发事件的方法(通常只在类的内部调用)
    protected virtual void OnMeetingNeeded()
    {
        MeetingNeeded?.Invoke();
    }
}

// 订阅事件的方法
public void SubscribeToMeeting(MeetingManager manager)
{
    manager.MeetingNeeded += OrganizeMeeting;
}

// 之前定义的组织会议的方法
public void OrganizeMeeting()
{
    Console.WriteLine("Meeting is being organized.");
}

// 在某处调用
public void SomeMethod()
{
    MeetingManager manager = new MeetingManager();
    SubscribeToMeeting(manager);
    manager.OnMeetingNeeded(); // 这将触发事件,调用OrganizeMeeting方法
}
  • 委托:是一种类型,定义了方法的签名,并允许你将方法作为参数传递。你可以把委托想象成“能够执行特定任务的人”。
  • 事件:是基于委托的,但它提供了一层封装,让外部代码只能订阅或取消订阅事件,而不能直接触发它。事件提供了一种发布/订阅模式,有助于代码的解耦和模块化。你可以把事件想象成“当某件事情发生时,通知所有关心这件事的人”。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐