详解C#委托与事件

· 浏览次数 : 19

小编点评

在C#中,委托是一种特殊的数据类型,它可以存储和方法的引用,使我们能够灵活地将方法作为参数传递给其他方法或组合多个方法。委托类似于函数指针,但具有类型安全、垃圾回收等现代语言特性。 委托的定义包括指定方法原型,包括返回类型和参数列表。例如: ```csharp public delegate int MyDelegate(int a, int b); ``` 要创建委托实例,使用`new`关键字加上委托类型和方法名: ```csharp MyDelegate myDelegate = new MyDelegate(AddNumbers); ``` 调用委托时,就像调用普通方法一样: ```csharp int result = myDelegate(5, 3); ``` 委托还可以被设计为多播,即支持同时调用多个方法。这可以通过组合多个委托来实现: ```csharp MyDelegate del1 = new MyDelegate(AddNumbers); MyDelegate del2 = new MyDelegate(MultiplyNumbers); MyDelegate combinedDel = del1 + del2; combinedDel(5, 3); // 先调用 AddNumbers,然后调用 MultiplyNumbers。 ``` 从C# 2.0开始,可以使用匿名方法定义委托: ```csharp MyDelegate anonMethod = delegate(int x, int y) { return x + y; }; ``` 或使用Lambda表达式: ```csharp MyDelegate lambdaExpr = (int x, int y) => x + y; ``` 事件是C#中用于封装消息发送机制的特殊委托类型,广泛应用于异步操作、UI交互和信号通知。事件基于委托类型定义,通常使用`System.EventHandler`或自定义委托类型。 事件定义示例: ```csharp public class Publisher { public delegate void MyEventHandler(object source, MyEventArgs args); private event MyEventHandler myEvent; public event MyEventHandler MyEvent { add { myEvent += value; } remove { myEvent -= value; } } public void RaiseEvent() { if (myEvent != null) { myEvent(this, new MyEventArgs()); } } } ``` 事件处理程序示例: ```csharp class Subscriber { public void OnMyEvent(object sender, MyEventArgs e) { Console.WriteLine("Event triggered."); } } ``` 订阅和取消订阅事件示例: ```csharp Publisher publisher = new Publisher(); Subscriber subscriber = new Subscriber(); publisher.MyEvent += subscriber.OnMyEvent; // 订阅 publisher.MyEvent -= subscriber.OnMyEvent; // 取消订阅 ``` 使用事件参数示例: ```csharp public class MyEventArgs : EventArgs { public string Message { get; set; } } public void RaiseEvent() { if (myEvent != null) { myEvent(this, new MyEventArgs { Message = "Hello, world!" }); } } ``` 总之,委托、事件和Lambda表达式是C#中用于实现灵活编程的强大工具,它们可以帮助我们更好地组织和管理代码。

正文

image

在C#中,委托是一种引用类型的数据类型,允许我们封装方法的引用。通过使用委托,我们可以将方法作为参数传递给其他方法,或者将多个方法组合在一起,从而实现更灵活的编程模式。委托类似于函数指针,但提供了类型安全和垃圾回收等现代语言特性。

基本概念

定义委托

定义委托需要指定它所代表的方法的原型,包括返回类型和参数列表。例如:

public delegate int MyDelegate(int a, int b);

这定义了一个名为MyDelegate的委托,它代表一个接受两个整数参数并返回一个整数的方法。

创建委托实例

创建委托实例时,可以使用new关键字加上委托类型和要封装的方法名:

MyDelegate myDelegate = new MyDelegate(AddNumbers);

其中AddNumbers是一个符合MyDelegate定义的方法。

调用委托

一旦有了委托实例,就可以像调用方法一样调用它:

int result = myDelegate(5, 3);

多播委托

委托可以被设计为“多播”的,这意味着它们可以调用多个方法。当调用多播委托时,所有注册的方法都会按顺序执行:

MyDelegate del1 = new MyDelegate(AddNumbers);
MyDelegate del2 = new MyDelegate(MultiplyNumbers);
MyDelegate combinedDel = del1 + del2;
combinedDel(5, 3); // 先调用 AddNumbers, 然后调用 MultiplyNumbers

匿名方法和Lambda表达式

从C# 2.0开始,可以使用匿名方法来定义委托:

MyDelegate anonMethod = delegate(int x, int y) { return x + y; };

而在C# 3.0之后,Lambda表达式成为更简洁的选择:

MyDelegate lambdaExpr = (int x, int y) => x + y;

事件

在C#中,事件是一种特殊的委托类型,用于封装消息的发送机制,通常用于组件之间或对象之间的通信。事件是.NET框架中处理异步操作、UI交互和信号通知的核心机制。下面详细介绍事件的概念、定义和使用。

事件的基本概念

事件允许一个类(事件发布者)向另一个或多个类(事件订阅者)广播信息,而无需直接调用接收方的任何方法。这实现了发布者和订阅者之间的解耦,使得代码更加模块化和可维护。

定义事件

事件基于委托类型定义,通常使用System.EventHandler或自定义的委托类型。定义事件时,通常在类中声明一个委托类型的私有字段,并在此基础上声明一个公共的事件属性。例如:

public class Publisher
{
    // 自定义委托类型
    public delegate void MyEventHandler(object source, MyEventArgs args);

    // 定义事件
    private event MyEventHandler myEvent;

    // 使用事件属性暴露事件
    public event MyEventHandler MyEvent
    {
        add { myEvent += value; }
        remove { myEvent -= value; }
    }

    // 触发事件
    public void RaiseEvent()
    {
        if (myEvent != null)
        {
            myEvent(this, new MyEventArgs());
        }
    }
}

在这个例子中,Publisher类有一个名为MyEvent的事件,它基于MyEventHandler委托类型。事件触发时,RaiseEvent方法会被调用,它会检查是否有订阅者,并调用所有订阅者的相应方法。

订阅和取消订阅事件

事件可以通过事件处理程序来订阅。事件处理程序是一个与事件委托类型匹配的方法。订阅事件时,将事件处理程序添加到事件中;取消订阅则移除该处理程序。

class Subscriber
{
    public void OnMyEvent(object sender, MyEventArgs e)
    {
        Console.WriteLine("Event triggered.");
    }
}

// 在某个地方订阅事件
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();
publisher.MyEvent += subscriber.OnMyEvent;

// 取消订阅事件
publisher.MyEvent -= subscriber.OnMyEvent;

使用事件参数

事件经常与事件参数一起使用,这些参数通常封装了事件发生时的附加信息。事件参数是通过继承EventArgs类来创建的。例如:

public class MyEventArgs : EventArgs
{
    public string Message { get; set; }
}

在触发事件时,可以创建事件参数的实例并传递给事件:

public void RaiseEvent()
{
    if (myEvent != null)
    {
        myEvent(this, new MyEventArgs { Message = "Hello, world!" });
    }
}

与详解C#委托与事件相似的内容:

详解C#委托与事件

在C#中,委托是一种引用类型的数据类型,允许我们封装方法的引用。通过使用委托,我们可以将方法作为参数传递给其他方法,或者将多个方法组合在一起,从而实现更灵活的编程模式。委托类似于函数指针,但提供了类型安全和垃圾回收等现代语言特性。 基本概念 定义委托 定义委托需要指定它所代表的方法的原型,包括返回类

【解惑】孜孜不倦,用足球赛程详解c#中的yield return用法

在一个知名企业赞助的足球联赛中,有256支球队参赛。为了确保比赛的顺利进行,企业指派了小悦负责熬夜加班制定每一个球队的赛程。尽管她对足球的了解并不多,但是她对待工作的认真态度却让人钦佩。 在小悦的努力下,她顺利完成了第一轮、第二轮和第三轮的比赛安排。然而,在大赛开始前的模拟比赛中,她发现了一个严重的

[转帖]C++:perf详解 + Flame Graph火焰图分析程序性能

因为项目需求,C++和java同时在搞,最近了解到Flame Graph火焰图这个工具,网上查了查资料,这里记录一下。 1 介绍 web site http://www.brendangregg.com/flamegraphs.html git: https://github.com/brendan

C++ 异常处理机制详解:轻松掌握异常处理技巧

C++ 异常处理 C++ 异常处理机制允许程序在运行时处理错误或意外情况。它提供了捕获和处理错误的一种结构化方式,使程序更加健壮和可靠。 异常处理的基本概念: 异常: 程序在运行时发生的错误或意外情况。 抛出异常: 使用 throw 关键字将异常传递给调用堆栈。 捕获异常: 使用 try-catch

C++ 访问说明符详解:封装数据,控制访问,提升安全性

C++ 访问说明符 访问说明符是 C++ 中控制类成员(属性和方法)可访问性的关键字。它们用于封装类数据并保护其免受意外修改或滥用。 三种访问说明符: public:允许从类外部的任何地方访问成员。 private:仅允许在类内部访问成员。 protected:允许在类内部及其派生类中访问成员。 示

C# System.Threading.Timer 详解及示例

System.Threading.Timer 基于线程池的定时器,相较于另外几种定时器,其安全性较高,适用性最强,因此本文通过重载、属性、方法等方面介绍此定时器的相关内容。

C 语言中的 sscanf 详解

一、函数介绍 函数原型:int sscanf(const char *str, const char *format, ...); 返 回 值:成功返回匹配成功的模式个数,失败返回 -1。 RETURN VALUE These functions return the number of input

详解AQS的7个同步组件

摘要:AQS的全称为Abstract Queued Synchronizer,是在J.U.C(java.util.concurrent)下子包中的类。 本文分享自华为云社区《【高并发】AQS案例详解》,作者: 冰 河。 AQS的全称为Abstract Queued Synchronizer,是在J.

深入剖析C++多态的实现与原理-详解

目录多态基础虚函数虚函数的继承虚类/虚基类重写/覆盖条件:概念:多态的条件其他的多态行为多态中子类可以不写virtual协变代码举例继承遗留问题解决析构函数具体解决方式:题目1答案:解析:题目2答案:C++11 override和finalfinal功能1:禁用继承使用场景:功能2:禁用重写使用场景

[转帖]详解redis-cli 命令

https://www.jb51.net/article/265208.htm 这篇文章主要介绍了redis-cli 命令详解,主要包括命令使用及使用info命令获取服务器的信息,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 命令使用: 1 redis-c