委托 #
一、委托概述 #
1.1 什么是委托 #
委托是类型安全的函数指针,可以引用方法。
1.2 委托特点 #
- 类型安全
- 支持多播
- 支持匿名方法
- 支持协变逆变
二、定义委托 #
2.1 基本语法 #
csharp
public delegate void NotifyHandler(string message);
public delegate int Calculator(int a, int b);
public delegate bool Predicate<T>(T item);
NotifyHandler handler = msg => Console.WriteLine(msg);
handler("Hello");
Calculator calc = (a, b) => a + b;
int result = calc(10, 20);
2.2 委托实例化 #
csharp
public delegate void PrintHandler(string message);
public void PrintToConsole(string message)
{
Console.WriteLine(message);
}
PrintHandler handler1 = new PrintHandler(PrintToConsole);
PrintHandler handler2 = PrintToConsole;
PrintHandler handler3 = delegate(string msg) { Console.WriteLine(msg); };
PrintHandler handler4 = msg => Console.WriteLine(msg);
handler1("Hello");
handler2("World");
三、多播委托 #
3.1 组合委托 #
csharp
public delegate void NotifyHandler(string message);
NotifyHandler handler1 = msg => Console.WriteLine($"处理器1: {msg}");
NotifyHandler handler2 = msg => Console.WriteLine($"处理器2: {msg}");
NotifyHandler handler3 = msg => Console.WriteLine($"处理器3: {msg}");
NotifyHandler multicast = handler1 + handler2;
multicast += handler3;
multicast("Hello");
multicast -= handler2;
multicast("World");
3.2 调用列表 #
csharp
public delegate void NotifyHandler(string message);
NotifyHandler handler = msg => Console.WriteLine(msg);
handler += msg => Console.WriteLine(msg.ToUpper());
handler += msg => Console.WriteLine(msg.ToLower());
Delegate[] delegates = handler.GetInvocationList();
foreach (var d in delegates)
{
var h = (NotifyHandler)d;
h("Test");
}
3.3 带返回值的多播 #
csharp
public delegate int Calculator();
Calculator calc = () => 1;
calc += () => 2;
calc += () => 3;
int result = calc();
Console.WriteLine(result);
foreach (var d in calc.GetInvocationList())
{
var c = (Calculator)d;
Console.WriteLine(c());
}
四、内置委托类型 #
4.1 Action #
csharp
Action action = () => Console.WriteLine("无参数");
action();
Action<string> print = s => Console.WriteLine(s);
print("Hello");
Action<int, string> process = (i, s) => Console.WriteLine($"{i}: {s}");
process(1, "Test");
4.2 Func #
csharp
Func<int> getRandom = () => Random.Shared.Next();
int random = getRandom();
Func<int, int> square = x => x * x;
int result = square(5);
Func<int, int, int> add = (a, b) => a + b;
int sum = add(10, 20);
Func<string, bool> isValid = s => !string.IsNullOrEmpty(s);
bool valid = isValid("Test");
4.3 Predicate #
csharp
Predicate<int> isEven = n => n % 2 == 0;
bool even = isEven(4);
Predicate<string> isLong = s => s.Length > 10;
bool longStr = isLong("Hello World");
var numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
List<int> evens = numbers.FindAll(isEven);
五、匿名方法 #
5.1 delegate关键字 #
csharp
Func<int, int, int> add = delegate(int a, int b)
{
return a + b;
};
Action<string> print = delegate(string s)
{
Console.WriteLine(s);
};
5.2 Lambda表达式 #
csharp
Func<int, int, int> add = (a, b) => a + b;
Func<int, int, int> add = (a, b) => { return a + b; };
Action<string> print = s => Console.WriteLine(s);
Action<string> print = s => { Console.WriteLine(s); };
Func<int, bool> isPositive = n => n > 0;
六、委托与事件 #
6.1 事件模式 #
csharp
public delegate void PriceChangedHandler(decimal oldPrice, decimal newPrice);
public class Stock
{
private decimal _price;
public event PriceChangedHandler PriceChanged;
public decimal Price
{
get => _price;
set
{
if (_price != value)
{
var oldPrice = _price;
_price = value;
PriceChanged?.Invoke(oldPrice, value);
}
}
}
}
var stock = new Stock();
stock.PriceChanged += (oldPrice, newPrice) =>
{
Console.WriteLine($"价格从 {oldPrice} 变为 {newPrice}");
};
stock.Price = 100;
stock.Price = 120;
七、实战示例 #
7.1 策略模式 #
csharp
public class Calculator
{
private Func<int, int, int> _strategy;
public Calculator(Func<int, int, int> strategy)
{
_strategy = strategy;
}
public void SetStrategy(Func<int, int, int> strategy)
{
_strategy = strategy;
}
public int Calculate(int a, int b) => _strategy(a, b);
}
var calc = new Calculator((a, b) => a + b);
Console.WriteLine(calc.Calculate(10, 20));
calc.SetStrategy((a, b) => a * b);
Console.WriteLine(calc.Calculate(10, 20));
7.2 过滤器 #
csharp
public static List<T> Filter<T>(IEnumerable<T> items, Predicate<T> predicate)
{
var result = new List<T>();
foreach (var item in items)
{
if (predicate(item))
{
result.Add(item);
}
}
return result;
}
var numbers = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var evens = Filter(numbers, n => n % 2 == 0);
var greaterThan5 = Filter(numbers, n => n > 5);
八、总结 #
委托要点:
| 要点 | 说明 |
|---|---|
| delegate | 定义委托 |
| Action | 无返回值委托 |
| Func | 有返回值委托 |
| Predicate | 返回bool的委托 |
| += -= | 多播组合 |
下一步,让我们学习事件!
最后更新:2026-03-26