C# 委托(Delegate)
在 C# 中,委托是一种类型安全的函数指针。委托可以用来将方法作为参数传递给其他方法,或者用于事件和回调机制。它允许你封装方法的调用,并在运行时动态地调用它。
1. 委托的基本定义
委托是一个类型,它定义了可以引用的方法的签名。委托类型的实例可以存储对特定方法的引用,类似于函数指针。
// 定义一个委托类型
public delegate void MyDelegate(string message);
// 使用委托
public class DelegateExample
{
public static void Main()
{
// 创建一个委托实例,指向一个方法
MyDelegate del = new MyDelegate(PrintMessage);
// 调用委托
del("Hello, world!");
}
// 定义一个与委托签名匹配的方法
public static void PrintMessage(string message)
{
Console.WriteLine(message);
}
}
输出:
Hello, world!
2. 委托的构成
委托由以下几个部分构成:
- 方法签名:定义了委托可以调用的方法类型(返回类型、参数类型)。
- 委托类型:定义了委托的类型,用于封装特定方法的调用。
- 委托实例:指向具体的方法,可以在运行时绑定不同的方法。
3. 委托的多播(Multicast Delegates)
委托不仅可以指向一个方法,还可以指向多个方法。这被称为多播委托。你可以使用 + 运算符将多个方法添加到一个委托实例中。
using System;
public delegate void MyDelegate(string message);
public class MulticastDelegateExample
{
public static void Main()
{
MyDelegate del1 = new MyDelegate(Method1);
MyDelegate del2 = new MyDelegate(Method2);
// 多播委托
MyDelegate multiDel = del1 + del2;
// 调用多播委托,依次调用委托链中的方法
multiDel("Hello, world!");
}
public static void Method1(string message)
{
Console.WriteLine("Method1: " + message);
}
public static void Method2(string message)
{
Console.WriteLine("Method2: " + message);
}
}
输出:
Method1: Hello, world!
Method2: Hello, world!
你还可以使用 - 运算符来移除委托链中的方法。
4. 委托作为参数传递
委托使得方法作为参数传递变得非常容易。以下是一个例子,展示如何将委托作为参数传递给另一个方法:
public class DelegateAsParameterExample
{
public static void Main()
{
// 定义委托
MyDelegate del = new MyDelegate(PrintMessage);
// 将委托作为参数传递
InvokeDelegate(del, "Hello from the delegate!");
}
public static void InvokeDelegate(MyDelegate del, string message)
{
del(message); // 调用传递过来的委托
}
public static void PrintMessage(string message)
{
Console.WriteLine(message);
}
}
输出:
Hello from the delegate!
5. 匿名方法和 Lambda 表达式
C# 允许使用匿名方法或Lambda 表达式来创建委托实例。这使得委托更加灵活。
使用匿名方法
public class AnonymousMethodExample
{
public static void Main()
{
MyDelegate del = delegate (string message)
{
Console.WriteLine("Anonymous method: " + message);
};
del("Hello, anonymous method!");
}
}
使用 Lambda 表达式
public class LambdaExpressionExample
{
public static void Main()
{
MyDelegate del = (message) => { Console.WriteLine("Lambda expression: " + message); };
del("Hello, lambda expression!");
}
}
6. 委托与事件
在 C# 中,委托通常与事件一起使用。事件是一种特殊的委托,用于对象与其他对象之间的通信。事件允许对象订阅(订阅者)和发布(发布者)消息,而无需知道其他对象的实现细节。
事件的使用示例:
using System;
public class EventPublisher
{
// 定义一个事件
public event MyDelegate MyEvent;
public void TriggerEvent(string message)
{
// 触发事件
MyEvent?.Invoke(message);
}
}
public class EventListener
{
public void HandleEvent(string message)
{
Console.WriteLine("Event received: " + message);
}
}
public class EventExample
{
public static void Main()
{
EventPublisher publisher = new EventPublisher();
EventListener listener = new EventListener();
// 订阅事件
publisher.MyEvent += listener.HandleEvent;
// 触发事件
publisher.TriggerEvent("Event triggered!");
}
}
输出:
Event received: Event triggered!
7. 委托的高级特性
- Func 委托:用于表示返回值的方法,最多可以有 16 个参数。
Func<int, int, int> add = (x, y) => x + y;
Console.WriteLine(add(5, 3)); // 输出:8
- Action 委托:用于表示没有返回值的方法,最多可以有 16 个参数。
Action<string> printMessage = (message) => Console.WriteLine(message);
printMessage("Hello from Action!"); // 输出:Hello from Action!
- Predicate 委托:用于表示返回
bool类型结果的方法,通常用于条件判断。
Predicate<int> isEven = (number) => number % 2 == 0;
Console.WriteLine(isEven(4)); // 输出:True
小结
- 委托是一种类型安全的函数指针,广泛应用于事件驱动和回调机制。
- 可以通过多播委托将多个方法关联到一个委托实例。
- 委托可以作为方法参数传递,使得代码更具灵活性。
- 匿名方法和Lambda 表达式使得委托的定义更加简洁。
- 委托通常与事件机制一起使用,是实现松耦合的常见方式。
委托在 C# 中是一个非常强大的工具,广泛应用于事件处理、异步编程、回调等多种场景。通过委托,程序可以更加灵活地进行方法调用和事件处理。