委托 #

一、委托概述 #

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