首页 > 编程语言 >C#:事件与委托

C#:事件与委托

时间:2024-08-23 13:25:17浏览次数:12  
标签:string 委托 C# void del 事件 message public

一、委托 (Delegates)

  1. 定义:委托是一种类型安全的方法引用,它可以指向一个或多个方法,并可以通过该委托调用这些方法。即委托该方法用以调用其他方法。

  2. 声明

    public delegate void MyDelegate(string message);
    
  3. 使用

    • 创建委托实例并指向方法:
    void MyMethod(string msg) 
    {
        Console.WriteLine(msg);
    }
    MyDelegate del = new MyDelegate(MyMethod);
    del("Hello, Delegates!"); // 输出:Hello, Delegates!
    
    • 委托可以指向多个方法(多播委托):
    del += AnotherMethod; // 追加方法
    del -= AnotherMethod; // 去除方法
    del += AnotherMethod; // 追加方法
    del("Hello again!"); // 将调用 MyMethod 和 AnotherMethod
    del = null //清空委托
    
    • 委托可以传参,只能绑定对应参数的方法,调用时传参:
    public delegate void MyDelegate(int number, string message);
    public void MyMethod(int number, string message) 
    {
     Console.WriteLine($"Number: {number}, Message: {message}");
    }
    MyDelegate del = new MyDelegate(MyMethod);
    del(42, "Hello, Delegates!"); // 输出:Number: 42, Message: Hello, Delegates!
    
    • 可以使用匿名方法和Lambda表达式
    //匿名方法
    MyDelegate del = delegate(int number, string message) 
    {
        Console.WriteLine($"Anonymous - Number: {number}, Message: {message}");
    };
    del(100, "Hello from Anonymous Method!"); 
    // 输出:Anonymous - Number: 100, Message: Hello from Anonymous Method!
    //Lambda表达式
    MyDelegate del = (number, message) => 
    {
        Console.WriteLine($"Lambda - Number: {number}, Message: {message}");
    };
    del(200, "Hello from Lambda!"); 
    // 输出:Lambda - Number: 200, Message: Hello from Lambda!
    

实际使用中,往往会直接使用事件而不是委托:

二、事件 (Events)

  1. 定义:事件是委托的封装,允许类或对象向其他类或对象提供通知。通常用于实现发布-订阅模式。
  2. 声明
    public class MyEventPublisher 
    {
        public event MyDelegate MyEvent; // 声明事件
    }
    
  3. 触发事件
    protected virtual void OnMyEvent(string message) 
    {
        MyEvent?.Invoke(message); // 触发事件
    }
    
  4. 订阅事件
    • 在另一个类中订阅事件:
    public class MyEventSubscriber 
    {
        public void Subscribe(MyEventPublisher publisher) 
        {
            publisher.MyEvent += HandleEvent; // 订阅事件
            publisher.MyEvent -= HandleEvent; // 取消事件
        }
    
        private void HandleEvent(string message) 
        {
            Console.WriteLine($"Event received: {message}");
        }
    }
    

为什么常用事件而不是委托(来源于网络)

  1. 解耦合性
    • 事件提供了一种更好的解耦合机制。发布者不需要知道订阅者的具体实现,允许多个订阅者同时响应同一事件,而不会影响彼此的实现。
  2. 灵活性和多播能力
    • 事件支持多播,可以有多个订阅者,而委托通常是单一的。当需要通知多个对象时,事件显得更为合适。
  3. 安全性
    • 事件的封装性使得外部无法直接调用事件,而只能通过订阅和触发的方式使用,这有助于避免不必要的调用和潜在的错误。
  4. 标准化和一致性
    • 使用事件是C#语言本身提供的特性,符合事件驱动编程的标准,容易被其他开发者理解和使用。Unity和许多框架也倾向于使用事件,从而保持API的一致性。
  5. 便于调试
    • 事件的订阅和触发方式更容易在调试时进行跟踪和监控,尤其是在复杂的应用程序中,可以快速识别事件的发送和接收情况。

为什么?(个人理解)

我认为事件的优点在于封装,在事件中,事件是个容器,包含其拥有的方法,给出统一的操作唤醒,不允许太过自主的调用,减少了对具体实现的依赖。
以此带来了解耦合,灵活多播,使用安全等优点。

三、示例代码

以下是一个完整的示例,演示如何使用委托和事件:

public delegate void MyDelegate(string message);

public class MyEventPublisher {
    public event MyDelegate MyEvent;

    public void TriggerEvent(string message) 
    {
        OnMyEvent(message);
    }

    protected virtual void OnMyEvent(string message) 
    {
        MyEvent?.Invoke(message);
    }
}

public class MyEventSubscriber {
    public void Subscribe(MyEventPublisher publisher) 
    {
        publisher.MyEvent += HandleEvent; // 订阅事件
    }

    private void HandleEvent(string message) 
    {
        Console.WriteLine($"Event received: {message}");
    }
}

class Program {
    static void Main(string[] args) 
    {
        MyEventPublisher publisher = new MyEventPublisher();
        MyEventSubscriber subscriber = new MyEventSubscriber();

        subscriber.Subscribe(publisher); // 订阅事件
        publisher.TriggerEvent("Hello, World!"); // 触发事件
    }
}
四、总结
  • 委托是一种类型安全的方法引用,允许将方法作为参数传递。
  • 事件是一种基于委托的通知机制,适用于实现观察者模式。
  • 委托和事件在C#中广泛用于异步编程、事件驱动编程等场景。

标签:string,委托,C#,void,del,事件,message,public
From: https://blog.csdn.net/m0_73727069/article/details/141463428

相关文章

  • Docker 的基本管理
    1.Docker的概述    如果要方便的创建运行在云平台上的应用,必须要脱离底层的硬件,同时还需要任何时间地点可获取这些资源,这正是Docker所能提供的。Docker的容器技术可以在一台主机上轻松为任何应用创建一个轻量级的、可移植的、自给自足的容器。通过这种容器打包应用......
  • C++:虚函数和虚表详细总结
    一、虚函数(VirtualFunctions)1.定义虚函数是基类中使用virtual关键字声明的成员函数,支持动态多态性。通过基类指针或引用调用虚函数时,会根据实际对象类型选择调用相应的函数实现。2.声明和定义虚函数的声明:classBase{public:virtualvoidshow();//......
  • C#/.NET这些实用的编程技巧你都会了吗?
    DotNetExercises介绍DotNetGuide专栏C#/.NET/.NETCore编程常用语法、算法、技巧、中间件、类库、工作业务实操练习集,配套详细的文章教程讲解,助你快速掌握C#/.NET/.NETCore中各种编程常用语法、算法、技巧、中间件、类库、工作业务实操等等。GitHub源码地址:https://github.co......
  • OpenCV(cv::RNG、cv::theRNG())
    目录1.cv::RNG1.1构造函数1.2常用方法1.3示例2.cv::theRNG()2.1使用方式2.2全局随机数生成器的优点2.3示例3.总结在OpenCV中,cv::RNG和cv::theRNG()是用于随机数生成的工具,常用于图像处理、计算机视觉中的数据生成、扰动操作等。1.cv::RNGcv::RNG是一个用于生......
  • Clion配置-运行多个单独cpp代码的main函数
    修改CMakeLists.txt文件为project(YourProjectName)set(CMAKE_CXX_STANDARD11)#遍历项目二级目录下所有的.cpp文件file(GLOBfiles*/*.cpp)foreach(file${files})string(REGEXREPLACE".+/(.+)/(.+)\\..*""\\1-\\2"exe${file})add_exec......
  • 分享一个基于ChatGPT实现基于Convars布局思路的实现过程
    一、思路在AI的大背景,应用层算法已经不是问题,那么程序员的差距主要在认知思维模式和创新上面。目前AI的局限主要却决于沟通的效率,这是双方的问题,AI可能理解能力不足,或者提问者表达能力不足。这里我以PDFsharp实现Grid布局模式分享一下基于GPT实现的过程。因为PDFsharp只提供了XG......
  • c++ chrono头文件内Duration 、time_point和Clock
    前言        http://t.csdnimg.cn/eprLZ中介绍了关于chrono的基本操作,本文来介绍chrono与其他类的关系。内容Duration    duration表示一段时间间隔template<classRep,classPeriod=std::ratio<1>>classduration        Rep表示持续时......
  • 实战:软件架构系列之【早期微服务架构Spring Cloud Netflix中的5大组件示例】
    概叙科普文:万字细说微服务及其框架Netflix,SpringCloud,SpringCloudAlibaba梳理_微服务netflixalibaba-CSDN博客科普文:微服务之技术选型SpringCloudAlibaba_微服务架构图阿里巴巴-CSDN博客SpringCloudNetflix是SpringCloud生态系统中最早期的一个子项目,它为Spr......
  • 用Scratch编程打造你的策略游戏:《保卫萝卜》入门教程
    保卫萝卜-小虎鲸Scratch资源站对于编程初学者来说,Scratch是一款非常友好的图形化编程工具。而将经典游戏与编程学习结合,更能激发学生的兴趣和创造力。今天,我们带来一个既有趣又具有挑战性的Scratch入门案例——《保卫萝卜》,让你在学习编程的同时,体验游戏设计的乐趣。作品简......
  • AtCoder Beginner Contest 中的小思维题
    078Dhttps://atcoder.jp/contests/abc078/tasks/arc085_b问题陈述我们有一副由\(N\)张牌组成的扑克牌。每张牌上都写着一个整数。从最上面开始的第\(i\)张牌上的整数是\(a_i\)。两个人X和Y将用这副扑克牌玩一个游戏。最初,X手中有一张写有\(Z\)的牌,Y手中有一张......