在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#委托与事件的更多相关文章

  1. 详解C#泛型(二) 获取C#中方法的执行时间及其代码注入 详解C#泛型(一) 详解C#委托和事件(二) 详解C#特性和反射(四) 记一次.net core调用SOAP接口遇到的问题 C# WebRequest.Create 锚点“#”字符问题 根据内容来产生一个二维码

    详解C#泛型(二)   一.自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型: void MyFunc<T>() //声明具有一个类型参数的泛型方法 { ...

  2. 详解C#委托和事件(一)

    委托(Delegate)是安全封装方法的类型,类似于C和C++中的函数指针,与函数指针不同的是,委托是面向对象的.类型安全的和可靠的: 一.委托类型是CTS中五种基础类型之一,是一种引用类型,表示对具 ...

  3. 详解C#委托,事件与回调函数

    .Net编程中最经常用的元素,事件必然是其中之一.无论在ASP.NET还是WINFrom开发中,窗体加载(Load),绘制(Paint),初始化(Init)等等.“protected void Pag ...

  4. 详解C#委托和事件(二)

    一.当我们使用关键字delegate声明一个自定义委托类型时,实际上是声明了一个该名称的类类型,继承自抽象类System.MulticastDelegate,还包含实例方法Invoke.BeginIn ...

  5. jQuery:详解jQuery中的事件(二)

    上一篇讲到jQuery中的事件,深入学习了加载DOM和事件绑定的相关知识,这篇主要深入讨论jQuery事件中的合成事件.事件冒泡和事件移除等内容. 接上篇jQuery:详解jQuery中的事件(一) ...

  6. 详解Vue 方法与事件处理器

      本篇文章主要介绍了详解Vue 方法与事件处理器 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 方法与事件处理器 方法处理器 可以用 v-on 指令监听 DOM 事件 ...

  7. ALSA声卡驱动中的DAPM详解之七:dapm事件机制(dapm event)

    前面的六篇文章,我们已经讨论了dapm关于动态电源管理的有关知识,包括widget的创建和初始化,widget之间的连接以及widget的上下电顺序等等.本章我们准备讨论dapm框架中的另一个机制:事 ...

  8. jQuery:详解jQuery中的事件(一)

    之前用过一些jQuery的动画和特效,但是用到的部分也不超过10%的样子,感觉好浪费啊——当然浪费的不是jQuery,而是Web资源.后来就想深入研究下jQuery的内部机理,读过两遍jQuery源代 ...

  9. localStorage、sessionStorage详解,以及storage事件使用

    有关localStorage和sessionStorage的特性. localStorage本身带有方法有 添加键值对:localStorage.setItem(key,value),如果key存在时 ...

  10. 【C#】详解C#委托

    目录结构: contents structure [+] 委托语法 泛型委托 委托链 lambda表达式 揭秘委托 类库中的委托 委托和反射 1.委托语法 本文会详细阐述委托的使用,以及实现,想必读者 ...

随机推荐

  1. 用 C 语言开发一门编程语言 — 抽象语法树

    目录 文章目录 目录 前文列表 抽象语法树的结构 使用递归来遍历树结构 实现求值计算 抽象语法树与行为树 前文列表 <用 C 语言开发一门编程语言 - 交互式解析器l> <用 C 语 ...

  2. 智能运维|AIRIOT智慧光伏管理解决方案

    ​ 随着新能源发展到今天,我国的能源产业已经形成产业化规模化的发展,"光伏能源"被广泛应用于电力.农业.市政照明甚至是军事领域. 以光伏电站为例,大量铺设的太阳能板运维成本相当高, ...

  3. CentOS7 防火墙(firewall)的命令详解

    复制代码 安装:yum install firewalld 1.firewalld的基本使用 启动: systemctl start firewalld 查看状态: systemctl status ...

  4. DashVector + DashScope升级多模态检索

    本教程在前述教程(DashVector + ModelScope玩转多模态检索)的基础之上,基于DashScope上新推出的ONE-PEACE通用多模态表征模型结合向量检索服务DashVector来对 ...

  5. Linux之SELinux

    1.什么是SELinux? 安全增强型 Linux(Security-Enhanced Linux)简称 SELinux,它是一个 Linux 内核模块,也是 Linux 的一个安全子系统. SELi ...

  6. Android 13 - Media框架(21)- ACodec(三)

    关注公众号免费阅读全文,进入音视频开发技术分享群! 这一节我们一起来了解 ACodec 是如何通过 configureCodec 方法配置 OMX 组件的,因为 configureCodec 代码比较 ...

  7. 《剑指offer - 题目2》

    题目描述 请实现一个函数,将一个字符串中的每个空格替换成"%20".例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy.   注意方 ...

  8. NOIP模拟87(多校20)

    前言 题目不难,但是个人感觉小细节有一些,然后有亿点卡常.. 感觉对于笛卡尔树的题目看不出算法,然后代码实现方面细节注意太少,常数有点大. 下次注意吧. T1 集合均值 解题思路 感觉应该是期望题里面 ...

  9. 使用Wesky.Net.Opentools库,一行代码实现实体类类型转换为Json格式字符串

    安装1.0.10以及以上版本的 Wesky.Net.OpenTools 包   包内,该功能的核心代码如下: 自定义属性: 实体类JSON模式生成器:   使用方式:引用上面的1.0.10版本或以上的 ...

  10. 高性能版本的零内存分配LikeString函数(ZeroMemAllocLikeOperator)

    继上一篇文章在.NET Core,除了VB的LikeString,还有其它方法吗?(四种LikeString实现分享)分享了四种实现方式,笔者对这四种实现方式,不管是执行性能还是内存分配性能上,都不太 ...