【进阶】C# 委托(Delegate)知识点总结归纳

1. 委托的基本概念

  • 定义:委托是一种类型安全的函数指针,用于封装方法(静态方法或实例方法)。

  • 核心作用:允许将方法作为参数传递,实现回调机制和事件处理。

  • 类型安全:委托在编译时会检查方法签名(参数类型和返回值类型)。

2. 委托的声明与使用

  • 声明语法:
cs 复制代码
delegate [返回类型] DelegateName([参数列表]);

示例:

cs 复制代码
delegate void MyDelegate(string message); // 无返回值,接受一个字符串参数
  • 实例化与调用
cs 复制代码
// 实例化委托(绑定方法)
MyDelegate del = new MyDelegate(MyMethod);

// 调用委托
del("Hello");

static void MyMethod(string msg) {
    Console.WriteLine(msg);
}

3. 多播委托(Multicast Delegate)

  • 特点 :一个委托实例可以绑定多个方法,通过 +=-= 运算符管理方法链。

  • 调用顺序:按添加顺序依次执行所有方法。

  • 返回值:若委托有返回值,只有最后一个方法的返回值会被保留。

cs 复制代码
MyDelegate del1 = Method1;
MyDelegate del2 = Method2;
MyDelegate combined = del1 + del2; // 合并委托
combined("Multi-cast"); // 依次调用 Method1 和 Method2

combined -= del1; // 移除委托

4. 匿名方法与Lambda表达式

  • 匿名方法 (C# 2.0):无需显式定义方法,直接通过 delegate 关键字绑定。
cs 复制代码
MyDelegate del = delegate(string msg) {
    Console.WriteLine("Anonymous: " + msg);
};
  • Lambda表达式(C# 3.0+):简化匿名方法的语法。
cs 复制代码
MyDelegate del = (msg) => Console.WriteLine("Lambda: " + msg);

5. 内置泛型委托

  • Action:无返回值的委托,最多支持16个参数。
cs 复制代码
Action<string> action = (s) => Console.WriteLine(s);
  • Func:有返回值的委托,最后一个泛型参数为返回值类型,最多支持16个参数(不包括返回值类型)。
cs 复制代码
Func<int, int, int> add = (a, b) => a + b;
int result = add(3, 5); // 返回8
  • Predicate :返回 bool 的委托,常用于条件判断,仅支持一个参数。
cs 复制代码
Predicate<int> isEven = num => num % 2 == 0;
bool result = isEven(4); // 返回true

6. 委托与事件

  • 事件本质:事件是基于委托的封装,提供更安全的订阅/取消订阅机制。

  • 事件声明

cs 复制代码
public event EventHandler MyEvent; // EventHandler 是内置委托
  • 触发事件
cs 复制代码
MyEvent?.Invoke(this, EventArgs.Empty); // 安全调用
  • 事件与委托的区别: 事件不能在类外部赋值和调用,只能在声明它的类内部触发(Invoke),外部只能订阅(+=)或取消订阅(-=)。

7. 协变与逆变(Covariance & Contravariance)

  • 协变(Covariance):允许委托返回类型是派生类(更具体类型)。(父类泛型委托装子类泛型委托)
cs 复制代码
delegate Animal GetAnimalDelegate();
GetAnimalDelegate del = GetDog; // Dog 是 Animal 的子类
Animal animal = del();

static Dog GetDog() => new Dog();
  • 逆变(Contravariance):允许委托参数是基类(更通用类型)。(子类泛型委托装父类泛型委托)
cs 复制代码
delegate void ProcessDogDelegate(Dog dog);
ProcessDogDelegate del = ProcessAnimal; // 参数类型为Animal(基类)
del(new Dog());

static void ProcessAnimal(Animal animal) { }

8. 注意事项

  • 内存泄漏 :长期持有委托可能导致对象无法释放,需及时取消订阅(-=)。

  • 线程安全:多线程中委托调用需确保线程同步。

  • 默认值处理:调用空委托会引发异常,需判空:

cs 复制代码
del?.Invoke("Hello");
相关推荐
我不是懒洋洋6 分钟前
预处理详解
c语言·开发语言·c++·windows·microsoft·青少年编程·visual studio
计算机安禾10 分钟前
【数据结构与算法】第14篇:队列(一):循环队列(顺序存储
c语言·开发语言·数据结构·c++·算法·visual studio
weixin_6495556733 分钟前
C语言程序设计第四版(何钦铭、颜晖)第十一章指针进阶之奇数值结点链表
c语言·开发语言·链表
书到用时方恨少!1 小时前
Python os 模块使用指南:系统交互的瑞士军刀
开发语言·python
我是大猴子1 小时前
事务失效的几种情况以及是为什么(详解)
java·开发语言
-许平安-1 小时前
MCP项目笔记六(PluginsLoader)
c++·笔记·raii·plugin system
开源盛世!!1 小时前
3.26-3.27学习笔记
笔记·学习
智者知已应修善业1 小时前
【文氏电桥振荡电路】2022-8-25
驱动开发·经验分享·笔记·硬件架构·硬件工程
武藤一雄1 小时前
C#:nameof 运算符全指南
开发语言·microsoft·c#·.net·.netcore
带娃的IT创业者2 小时前
WeClaw_40_系统监控与日志体系:多层次日志架构与Trace追踪
java·开发语言·python·架构·系统监控·日志系统·链路追踪