C# 委托的定义和使用、事件与委托
委托的定义和使用
委托可以初步理解为一个函数类型的变量(引用类型的变量),表示对一个或多个方法的引用。
官网解释 delegate
使用委托时,一般需要先声明委托类型,再使用委托类型定义变量。
那么如何声明委托类型?使用关键字 delegate
public delegate void KeyDelegate(string key);
再定义一个对应委托类型的处理函数,等会使用委托时,就会把参数传递到这个处理函数去处理。
public static void PrintString(string key)
{
Console.WriteLine(key);
}
如何使用委托?实例化委托类型的变量
KeyDelegate keyAevent = new KeyDelegate(DelegateFunc.PrintString);
一个委托可以绑定多个事件处理函数,下面的语句中就是在定义委托变量之后,又通过 += 为其绑定新的事件处理函数
multiEvent += new KeyDelegate(DelegateFunc.PrintString2);
为委托变量绑定多个事件处理函数后,再使用委托变量,就会自动调用委托对应的所有事件处理函数
multiEvent("B");
委托和接口的区别
定义上的区别
接口(interface)是约束某个类,应该具备那些功能的一个集合。接口约束了类应该具备那些方法,便于类的管理和扩展,同时还能解决类的单继承问题(在 C# 中只能类单继承,但是可以继承多个接口)。
委托(delegate)变量是一个或多个方法,组成的一个集合,使用运算符 += -= 可以对这个方法集合进行操作。
适用场景不同
在以下情况中适合使用接口:
- 已继承了某个类,无法再继承其他类,但是又希望继续拓展其他功能时
- 完全抽象时
- 多人协作需要约束类的功能时
在以下情况中适合使用委托:
- 在事件处理的流程中使用委托:定义事件(使用委托)、绑定事件(操作委托对应的方法集合)、事件处理函数、呼叫事件
事件
事件是对委托的一层包装,委托类型的变量,使用 发布-订阅 的模型。
发布器:定义事件和委托,为事件和委托绑定处理函数
订阅器:接受事件,提供事件处理逻辑
声明委托
public delegate void KeyDelegate(string key);
声明事件
public static event KeyDelegate? keyEvent;
绑定事件
EventHandler.keyEvent += DelegateFunc.PrintString2;
定义事件处理函数(与委托类型对应)
public static void PrintString2(string key)
{
Console.WriteLine("-" + key + "-");
}
呼叫事件
keyEvent?.Invoke(key);
补充
另一种事件定义 public static event Action<string> keyEvent;
的写法,其中 Action<T>
是委托的简写方式,可以快速声明委托类型的事件变量,而不像传统的委托写法,需要先声明委托类型,再利用委托类型,实例化一个委托变量来使用
完整示例代码
using System;
// 1.1 声明一个委托类型 KeyDelegate
public delegate void KeyDelegate(string key);
class DelegateFunc
{
// 1.2 声明与委托类型对应的方法 返回值、参数列表与委托类型 KeyDelegate 保持一致
public static void PrintString(string key)
{
Console.WriteLine(key);
}
// 2.3 事件处理函数
public static void PrintString2(string key)
{
Console.WriteLine("-" + key + "-");
}
}
public static class EventHandler
{
// 2.1 声明事件前,必须事先声明一个委托类型 例如 KeyDelegate
public static event KeyDelegate? keyEvent;
// 2.4 呼叫事件
public static void CallKeyEvent(string key)
{
keyEvent?.Invoke(key);
}
}
class Program
{
static void Main()
{
// 1.3 实例化一个委托类型的变量 keyAevent ,对应接受委托的函数 DelegateFunc.PrintString
KeyDelegate keyAevent = new KeyDelegate(DelegateFunc.PrintString);
KeyDelegate multiEvent;
multiEvent = keyAevent;
// 1.4 一个委托可以使用 += 操作符 绑定多个事件处理函数
multiEvent += new KeyDelegate(DelegateFunc.PrintString2);
// 2.2 绑定事件
EventHandler.keyEvent += DelegateFunc.PrintString2;
while (true)
{
ConsoleKeyInfo key = Console.ReadKey();
switch (key.Key)
{
case ConsoleKey.A:
// 1.4 aA
keyAevent("A");
break;
case ConsoleKey.B:
// 1.4 bB
// 1.4 -B-
multiEvent("B");
break;
case ConsoleKey.C:
// 2.4 c-C-
EventHandler.CallKeyEvent("C");
break;
case ConsoleKey.Q:
Console.Clear();
return;
default:
Console.WriteLine();
break;
}
}
}
}