本章目标

通过本章学习,你将掌握: - 委托的概念和基本使用 - 多播委托和委托链 - 匿名方法和Lambda表达式 - 事件的定义和使用 - 事件处理模式 - 观察者模式的实现 - 委托和事件的最佳实践

1. 委托基础

1.1 委托的概念

委托是一种类型,表示对具有特定签名的方法的引用。可以将委托看作是函数指针的类型安全版本。

// 声明委托类型
public delegate int MathOperation(int x, int y);
public delegate void MessageHandler(string message);
public delegate bool Predicate<T>(T item);
public delegate TResult Func<T, TResult>(T input);

// 基本委托使用示例
public class DelegateBasics
{
    // 符合MathOperation委托签名的方法
    public static int Add(int x, int y)
    {
        Console.WriteLine($"执行加法:{x} + {y}");
        return x + y;
    }
    
    public static int Subtract(int x, int y)
    {
        Console.WriteLine($"执行减法:{x} - {y}");
        return x - y;
    }
    
    public static int Multiply(int x, int y)
    {
        Console.WriteLine($"执行乘法:{x} × {y}");
        return x * y;
    }
    
    public static int Divide(int x, int y)
    {
        if (y == 0)
            throw new DivideByZeroException("除数不能为零");
        Console.WriteLine($"执行除法:{x} ÷ {y}");
        return x / y;
    }
    
    // 符合MessageHandler委托签名的方法
    public static void PrintMessage(string message)
    {
        Console.WriteLine($"[打印] {message}");
    }
    
    public static void LogMessage(string message)
    {
        Console.WriteLine($"[日志] {DateTime.Now:HH:mm:ss} - {message}");
    }
    
    public static void DebugMessage(string message)
    {
        Console.WriteLine($"[调试] {message.ToUpper()}");
    }
}

// 委托使用示例
public class DelegateDemo
{
    public static void DemonstrateDelegateBasics()
    {
        Console.WriteLine("=== 委托基础演示 ===");
        
        // 创建委托实例
        Console.WriteLine("\n--- 基本委托使用 ---");
        MathOperation operation;
        
        // 方法1:使用new关键字
        operation = new MathOperation(DelegateBasics.Add);
        int result1 = operation(10, 5);
        Console.WriteLine($"结果:{result1}");
        
        // 方法2:直接赋值(推荐)
        operation = DelegateBasics.Subtract;
        int result2 = operation(10, 5);
        Console.WriteLine($"结果:{result2}");
        
        // 方法3:使用方法组
        operation = DelegateBasics.Multiply;
        int result3 = operation(10, 5);
        Console.WriteLine($"结果:{result3}");
        
        // 委托作为参数传递
        Console.WriteLine("\n--- 委托作为参数 ---");
        ExecuteOperation(DelegateBasics.Add, 15, 25);
        ExecuteOperation(DelegateBasics.Divide, 20, 4);
        
        // 委托数组
        Console.WriteLine("\n--- 委托数组 ---");
        MathOperation[] operations = {
            DelegateBasics.Add,
            DelegateBasics.Subtract,
            DelegateBasics.Multiply,
            DelegateBasics.Divide
        };
        
        int x = 12, y = 3;
        foreach (MathOperation op in operations)
        {
            try
            {
                int result = op(x, y);
                Console.WriteLine($"结果:{result}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"错误:{ex.Message}");
            }
        }
        
        // 消息处理委托
        Console.WriteLine("\n--- 消息处理委托 ---");
        MessageHandler handler = DelegateBasics.PrintMessage;
        handler("Hello Delegate!");
        
        handler = DelegateBasics.LogMessage;
        handler("这是一条日志消息");
        
        handler = DelegateBasics.DebugMessage;
        handler("Debug Information");
    }
    
    private static void ExecuteOperation(MathOperation operation, int x, int y)
    {
        try
        {
            int result = operation(x, y);
            Console.WriteLine($"操作结果:{result}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"操作失败:{ex.Message}");
        }
    }
}

1.2 多播委托

// 多播委托示例
public class MulticastDelegateDemo
{
    public static void DemonstrateMulticastDelegates()
    {
        Console.WriteLine("\n=== 多播委托演示 ===");
        
        // 创建多播委托
        Console.WriteLine("\n--- 多播委托组合 ---");
        MessageHandler handler = null;
        
        // 使用 += 添加方法
        handler += DelegateBasics.PrintMessage;
        handler += DelegateBasics.LogMessage;
        handler += DelegateBasics.DebugMessage;
        
        Console.WriteLine("调用多播委托:");
        handler("多播委托测试消息");
        
        // 使用 -= 移除方法
        Console.WriteLine("\n--- 移除委托方法 ---");
        handler -= DelegateBasics.DebugMessage;
        Console.WriteLine("移除DebugMessage后:");
        handler("移除后的消息");
        
        // 委托链的顺序
        Console.WriteLine("\n--- 委托链顺序 ---");
        MessageHandler orderedHandler = null;
        orderedHandler += msg => Console.WriteLine($"第一个:{msg}");
        orderedHandler += msg => Console.WriteLine($"第二个:{msg}");
        orderedHandler += msg => Console.WriteLine($"第三个:{msg}");
        
        Console.WriteLine("按顺序执行:");
        orderedHandler("顺序测试");
        
        // 获取调用列表
        Console.WriteLine("\n--- 委托调用列表 ---");
        if (handler != null)
        {
            Delegate[] invocationList = handler.GetInvocationList();
            Console.WriteLine($"委托链中有 {invocationList.Length} 个方法:");
            
            for (int i = 0; i < invocationList.Length; i++)
            {
                var method = invocationList[i].Method;
                Console.WriteLine($"  {i + 1}. {method.DeclaringType?.Name}.{method.Name}");
            }
        }
        
        // 多播委托的返回值(只返回最后一个方法的结果)
        Console.WriteLine("\n--- 多播委托返回值 ---");
        MathOperation multiMath = null;
        multiMath += DelegateBasics.Add;
        multiMath += DelegateBasics.Multiply;
        
        int finalResult = multiMath(5, 3);
        Console.WriteLine($"多播委托最终返回值:{finalResult}"); // 只返回最后一个方法的结果
    }
}

// 委托的异常处理
public class DelegateExceptionHandling
{
    public static void ThrowException(string message)
    {
        Console.WriteLine($"即将抛出异常:{message}");
        throw new InvalidOperationException($"故意抛出的异常:{message}");
    }
    
    public static void SafeMethod(string message)
    {
        Console.WriteLine($"安全方法:{message}");
    }
    
    public static void DemonstrateExceptionHandling()
    {
        Console.WriteLine("\n=== 委托异常处理演示 ===");
        
        MessageHandler handler = SafeMethod;
        handler += ThrowException;
        handler += SafeMethod; // 这个方法不会被执行,因为前面的方法抛出了异常
        
        try
        {
            Console.WriteLine("调用包含异常的委托链:");
            handler("测试消息");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"捕获异常:{ex.Message}");
        }
        
        // 安全调用委托链中的每个方法
        Console.WriteLine("\n--- 安全调用委托链 ---");
        SafeInvokeAll(handler, "安全调用测试");
    }
    
    private static void SafeInvokeAll(MessageHandler handler, string message)
    {
        if (handler == null) return;
        
        foreach (MessageHandler singleHandler in handler.GetInvocationList())
        {
            try
            {
                singleHandler(message);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"方法 {singleHandler.Method.Name} 执行失败:{ex.Message}");
            }
        }
    }
}

1.3 内置委托类型

// 内置委托类型使用
public class BuiltInDelegatesDemo
{
    public static void DemonstrateBuiltInDelegates()
    {
        Console.WriteLine("\n=== 内置委托类型演示 ===");
        
        // Action委托(无返回值)
        Console.WriteLine("\n--- Action委托 ---");
        Action simpleAction = () => Console.WriteLine("无参数Action");
        simpleAction();
        
        Action<string> stringAction = message => Console.WriteLine($"Action<string>: {message}");
        stringAction("Hello Action");
        
        Action<int, string> multiParamAction = (num, text) => 
            Console.WriteLine($"Action<int, string>: {num} - {text}");
        multiParamAction(42, "Answer");
        
        // Func委托(有返回值)
        Console.WriteLine("\n--- Func委托 ---");
        Func<int> getRandomNumber = () => new Random().Next(1, 100);
        Console.WriteLine($"随机数:{getRandomNumber()}");
        
        Func<int, int, int> add = (x, y) => x + y;
        Console.WriteLine($"加法结果:{add(10, 20)}");
        
        Func<string, int> getStringLength = str => str?.Length ?? 0;
        Console.WriteLine($"字符串长度:{getStringLength("Hello World")}");
        
        Func<int, bool> isEven = number => number % 2 == 0;
        Console.WriteLine($"42是偶数:{isEven(42)}");
        Console.WriteLine($"43是偶数:{isEven(43)}");
        
        // Predicate委托(返回bool)
        Console.WriteLine("\n--- Predicate委托 ---");
        Predicate<int> isPositive = x => x > 0;
        Predicate<string> isNotEmpty = str => !string.IsNullOrEmpty(str);
        
        Console.WriteLine($"5是正数:{isPositive(5)}");
        Console.WriteLine($"-3是正数:{isPositive(-3)}");
        Console.WriteLine($"'Hello'非空:{isNotEmpty("Hello")}");
        Console.WriteLine($"''非空:{isNotEmpty("")}");
        
        // 使用内置委托进行集合操作
        Console.WriteLine("\n--- 集合操作 ---");
        int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        
        // 使用Predicate过滤
        var evenNumbers = Array.FindAll(numbers, isEven.Invoke);
        Console.WriteLine($"偶数:[{string.Join(", ", evenNumbers)}]");
        
        // 使用Func转换
        var squares = Array.ConvertAll(numbers, x => x * x);
        Console.WriteLine($"平方:[{string.Join(", ", squares)}]");
        
        // 使用Action遍历
        Console.WriteLine("遍历数组:");
        Array.ForEach(numbers, num => Console.Write($"{num} "));
        Console.WriteLine();
    }
}

2. Lambda表达式和匿名方法

2.1 Lambda表达式

public class LambdaExpressionsDemo
{
    public static void DemonstrateLambdaExpressions()
    {
        Console.WriteLine("\n=== Lambda表达式演示 ===");
        
        // 基本Lambda表达式
        Console.WriteLine("\n--- 基本Lambda表达式 ---");
        
        // 无参数Lambda
        Func<string> getCurrentTime = () => DateTime.Now.ToString("HH:mm:ss");
        Console.WriteLine($"当前时间:{getCurrentTime()}");
        
        // 单参数Lambda(可省略括号)
        Func<int, int> square = x => x * x;
        Console.WriteLine($"5的平方:{square(5)}");
        
        // 多参数Lambda
        Func<int, int, int> power = (baseNum, exponent) => 
        {
            int result = 1;
            for (int i = 0; i < exponent; i++)
            {
                result *= baseNum;
            }
            return result;
        };
        Console.WriteLine($"2的3次方:{power(2, 3)}");
        
        // 表达式体Lambda vs 语句体Lambda
        Console.WriteLine("\n--- 表达式体 vs 语句体 ---");
        
        // 表达式体(单行)
        Func<double, double> circleArea = radius => Math.PI * radius * radius;
        
        // 语句体(多行)
        Func<double, string> circleInfo = radius =>
        {
            double area = Math.PI * radius * radius;
            double circumference = 2 * Math.PI * radius;
            return $"半径:{radius}, 面积:{area:F2}, 周长:{circumference:F2}";
        };
        
        Console.WriteLine($"圆形面积:{circleArea(5):F2}");
        Console.WriteLine($"圆形信息:{circleInfo(5)}");
        
        // Lambda表达式捕获外部变量
        Console.WriteLine("\n--- 变量捕获 ---");
        int multiplier = 10;
        Func<int, int> multiplyByTen = x => x * multiplier;
        
        Console.WriteLine($"5 × {multiplier} = {multiplyByTen(5)}");
        
        multiplier = 20; // 修改外部变量
        Console.WriteLine($"5 × {multiplier} = {multiplyByTen(5)}"); // Lambda会捕获最新值
        
        // 复杂Lambda表达式
        Console.WriteLine("\n--- 复杂Lambda表达式 ---");
        
        var people = new[]
        {
            new { Name = "张三", Age = 25, City = "北京" },
            new { Name = "李四", Age = 30, City = "上海" },
            new { Name = "王五", Age = 22, City = "广州" },
            new { Name = "赵六", Age = 28, City = "深圳" }
        };
        
        // 过滤
        var adults = people.Where(p => p.Age >= 25).ToArray();
        Console.WriteLine($"25岁及以上的人 ({adults.Length}个):");
        foreach (var person in adults)
        {
            Console.WriteLine($"  {person.Name}({person.Age}岁) - {person.City}");
        }
        
        // 排序
        var sortedByAge = people.OrderBy(p => p.Age).ToArray();
        Console.WriteLine($"\n按年龄排序:");
        foreach (var person in sortedByAge)
        {
            Console.WriteLine($"  {person.Name}({person.Age}岁) - {person.City}");
        }
        
        // 投影
        var nameAndCity = people.Select(p => $"{p.Name} - {p.City}").ToArray();
        Console.WriteLine($"\n姓名和城市:");
        foreach (var info in nameAndCity)
        {
            Console.WriteLine($"  {info}");
        }
        
        // 聚合
        var averageAge = people.Average(p => p.Age);
        var totalAge = people.Sum(p => p.Age);
        Console.WriteLine($"\n平均年龄:{averageAge:F1}岁");
        Console.WriteLine($"年龄总和:{totalAge}岁");
    }
}

// 匿名方法(C# 2.0语法,现在较少使用)
public class AnonymousMethodsDemo
{
    public static void DemonstrateAnonymousMethods()
    {
        Console.WriteLine("\n=== 匿名方法演示 ===");
        
        // 匿名方法语法
        Console.WriteLine("\n--- 匿名方法语法 ---");
        
        // 使用delegate关键字
        Func<int, int> doubleValue = delegate(int x) { return x * 2; };
        Console.WriteLine($"匿名方法:5 × 2 = {doubleValue(5)}");
        
        // 对比Lambda表达式
        Func<int, int> doubleValueLambda = x => x * 2;
        Console.WriteLine($"Lambda表达式:5 × 2 = {doubleValueLambda(5)}");
        
        // 匿名方法捕获变量
        Console.WriteLine("\n--- 匿名方法变量捕获 ---");
        int factor = 3;
        
        Func<int, int> multiplyByFactor = delegate(int x)
        {
            Console.WriteLine($"匿名方法中的factor值:{factor}");
            return x * factor;
        };
        
        Console.WriteLine($"结果:{multiplyByFactor(7)}");
        
        factor = 5;
        Console.WriteLine($"修改factor后的结果:{multiplyByFactor(7)}");
    }
}

2.2 高级Lambda应用

public class AdvancedLambdaDemo
{
    // 函数式编程风格
    public static void DemonstrateFunctionalProgramming()
    {
        Console.WriteLine("\n=== 函数式编程风格 ===");
        
        // 高阶函数
        Console.WriteLine("\n--- 高阶函数 ---");
        
        // 返回函数的函数
        Func<int, Func<int, int>> CreateMultiplier = factor => x => x * factor;
        
        var multiplyBy2 = CreateMultiplier(2);
        var multiplyBy5 = CreateMultiplier(5);
        
        Console.WriteLine($"2倍函数:{multiplyBy2(10)}");
        Console.WriteLine($"5倍函数:{multiplyBy5(10)}");
        
        // 函数组合
        Func<int, int> addOne = x => x + 1;
        Func<int, int> multiplyByTwo = x => x * 2;
        
        // 组合函数:先加1,再乘2
        Func<int, int> addOneThenMultiplyByTwo = x => multiplyByTwo(addOne(x));
        Console.WriteLine($"组合函数 (5+1)*2 = {addOneThenMultiplyByTwo(5)}");
        
        // 通用函数组合器
        Func<T, TResult> Compose<T, TMiddle, TResult>(
            Func<T, TMiddle> first, 
            Func<TMiddle, TResult> second) => x => second(first(x));
        
        var composedFunction = Compose(addOne, multiplyByTwo);
        Console.WriteLine($"通用组合器 (7+1)*2 = {composedFunction(7)}");
        
        // 柯里化(Currying)
        Console.WriteLine("\n--- 柯里化 ---");
        
        // 普通函数
        Func<int, int, int, int> add3Numbers = (x, y, z) => x + y + z;
        
        // 柯里化版本
        Func<int, Func<int, Func<int, int>>> curriedAdd = x => y => z => x + y + z;
        
        var add10 = curriedAdd(10);
        var add10And20 = add10(20);
        var result = add10And20(30);
        
        Console.WriteLine($"柯里化结果:{result}");
        Console.WriteLine($"直接调用:{curriedAdd(10)(20)(30)}");
        
        // 偏函数应用
        Console.WriteLine("\n--- 偏函数应用 ---");
        
        Func<string, string, string, string> formatMessage = 
            (prefix, message, suffix) => $"{prefix}{message}{suffix}";
        
        // 创建偏函数
        Func<string, string> createWarning = message => formatMessage("[警告] ", message, " !");
        Func<string, string> createError = message => formatMessage("[错误] ", message, " !!!");
        
        Console.WriteLine(createWarning("这是一个警告"));
        Console.WriteLine(createError("这是一个错误"));
    }
    
    // 递归Lambda表达式
    public static void DemonstrateRecursiveLambda()
    {
        Console.WriteLine("\n--- 递归Lambda表达式 ---");
        
        // 阶乘函数
        Func<int, int> factorial = null;
        factorial = n => n <= 1 ? 1 : n * factorial(n - 1);
        
        Console.WriteLine($"5! = {factorial(5)}");
        Console.WriteLine($"7! = {factorial(7)}");
        
        // 斐波那契数列
        Func<int, long> fibonacci = null;
        fibonacci = n => n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
        
        Console.WriteLine("斐波那契数列前10项:");
        for (int i = 0; i < 10; i++)
        {
            Console.Write($"{fibonacci(i)} ");
        }
        Console.WriteLine();
        
        // 使用记忆化优化递归
        var memoizedFib = CreateMemoizedFunction(fibonacci);
        
        var sw = System.Diagnostics.Stopwatch.StartNew();
        long result1 = fibonacci(40);
        sw.Stop();
        Console.WriteLine($"普通递归 fibonacci(40) = {result1}, 耗时: {sw.ElapsedMilliseconds}ms");
        
        sw.Restart();
        long result2 = memoizedFib(40);
        sw.Stop();
        Console.WriteLine($"记忆化递归 fibonacci(40) = {result2}, 耗时: {sw.ElapsedMilliseconds}ms");
    }
    
    // 记忆化函数
    private static Func<T, TResult> CreateMemoizedFunction<T, TResult>(Func<T, TResult> function)
    {
        var cache = new Dictionary<T, TResult>();
        return input =>
        {
            if (cache.TryGetValue(input, out TResult cachedResult))
            {
                return cachedResult;
            }
            
            TResult result = function(input);
            cache[input] = result;
            return result;
        };
    }
}

3. 事件基础

3.1 事件的概念和定义

// 事件参数基类
public class EventArgs
{
    public static readonly EventArgs Empty = new EventArgs();
}

// 自定义事件参数
public class TemperatureChangedEventArgs : EventArgs
{
    public double OldTemperature { get; }
    public double NewTemperature { get; }
    public double Change => NewTemperature - OldTemperature;
    public DateTime Timestamp { get; }
    
    public TemperatureChangedEventArgs(double oldTemp, double newTemp)
    {
        OldTemperature = oldTemp;
        NewTemperature = newTemp;
        Timestamp = DateTime.Now;
    }
}

public class FileProcessedEventArgs : EventArgs
{
    public string FileName { get; }
    public long FileSize { get; }
    public bool Success { get; }
    public string ErrorMessage { get; }
    public TimeSpan ProcessingTime { get; }
    
    public FileProcessedEventArgs(string fileName, long fileSize, bool success, 
        string errorMessage = null, TimeSpan processingTime = default)
    {
        FileName = fileName;
        FileSize = fileSize;
        Success = success;
        ErrorMessage = errorMessage;
        ProcessingTime = processingTime;
    }
}

// 温度监控器类
public class TemperatureMonitor
{
    private double temperature;
    private readonly double minTemperature;
    private readonly double maxTemperature;
    
    // 事件声明
    public event EventHandler<TemperatureChangedEventArgs> TemperatureChanged;
    public event EventHandler<EventArgs> OverheatingDetected;
    public event EventHandler<EventArgs> FreezingDetected;
    
    public TemperatureMonitor(double minTemp = -10, double maxTemp = 50)
    {
        minTemperature = minTemp;
        maxTemperature = maxTemp;
        temperature = 20; // 默认室温
    }
    
    public double Temperature
    {
        get => temperature;
        set
        {
            if (Math.Abs(temperature - value) > 0.01) // 避免频繁触发
            {
                double oldTemp = temperature;
                temperature = value;
                
                // 触发温度变化事件
                OnTemperatureChanged(new TemperatureChangedEventArgs(oldTemp, temperature));
                
                // 检查异常温度
                CheckTemperatureAlerts();
            }
        }
    }
    
    public string Status
    {
        get
        {
            if (temperature > maxTemperature) return "过热";
            if (temperature < minTemperature) return "过冷";
            return "正常";
        }
    }
    
    // 事件触发方法(受保护的虚方法)
    protected virtual void OnTemperatureChanged(TemperatureChangedEventArgs e)
    {
        TemperatureChanged?.Invoke(this, e);
    }
    
    protected virtual void OnOverheatingDetected()
    {
        OverheatingDetected?.Invoke(this, EventArgs.Empty);
    }
    
    protected virtual void OnFreezingDetected()
    {
        FreezingDetected?.Invoke(this, EventArgs.Empty);
    }
    
    private void CheckTemperatureAlerts()
    {
        if (temperature > maxTemperature)
        {
            OnOverheatingDetected();
        }
        else if (temperature < minTemperature)
        {
            OnFreezingDetected();
        }
    }
    
    // 模拟温度变化
    public void SimulateTemperatureChange(double targetTemp, int steps = 10)
    {
        double step = (targetTemp - temperature) / steps;
        
        for (int i = 0; i < steps; i++)
        {
            Temperature += step;
            Thread.Sleep(100); // 模拟时间延迟
        }
    }
}

// 文件处理器类
public class FileProcessor
{
    public event EventHandler<FileProcessedEventArgs> FileProcessed;
    public event EventHandler<EventArgs> ProcessingStarted;
    public event EventHandler<EventArgs> ProcessingCompleted;
    
    private int processedCount = 0;
    private int totalFiles = 0;
    
    public int ProcessedCount => processedCount;
    public int TotalFiles => totalFiles;
    public double Progress => totalFiles > 0 ? (double)processedCount / totalFiles * 100 : 0;
    
    public void ProcessFiles(string[] filePaths)
    {
        totalFiles = filePaths.Length;
        processedCount = 0;
        
        OnProcessingStarted();
        
        foreach (string filePath in filePaths)
        {
            ProcessSingleFile(filePath);
        }
        
        OnProcessingCompleted();
    }
    
    private void ProcessSingleFile(string filePath)
    {
        var stopwatch = System.Diagnostics.Stopwatch.StartNew();
        bool success = false;
        string errorMessage = null;
        long fileSize = 0;
        
        try
        {
            if (File.Exists(filePath))
            {
                var fileInfo = new FileInfo(filePath);
                fileSize = fileInfo.Length;
                
                // 模拟文件处理
                Thread.Sleep(new Random().Next(100, 500));
                
                // 模拟处理成功/失败
                success = new Random().NextDouble() > 0.1; // 90%成功率
                
                if (!success)
                {
                    errorMessage = "模拟处理失败";
                }
            }
            else
            {
                errorMessage = "文件不存在";
            }
        }
        catch (Exception ex)
        {
            errorMessage = ex.Message;
        }
        finally
        {
            stopwatch.Stop();
            processedCount++;
            
            OnFileProcessed(new FileProcessedEventArgs(
                Path.GetFileName(filePath), 
                fileSize, 
                success, 
                errorMessage, 
                stopwatch.Elapsed));
        }
    }
    
    protected virtual void OnFileProcessed(FileProcessedEventArgs e)
    {
        FileProcessed?.Invoke(this, e);
    }
    
    protected virtual void OnProcessingStarted()
    {
        ProcessingStarted?.Invoke(this, EventArgs.Empty);
    }
    
    protected virtual void OnProcessingCompleted()
    {
        ProcessingCompleted?.Invoke(this, EventArgs.Empty);
    }
}

3.2 事件使用示例

public class EventDemo
{
    public static void DemonstrateEvents()
    {
        Console.WriteLine("\n=== 事件演示 ===");
        
        // 温度监控演示
        Console.WriteLine("\n--- 温度监控演示 ---");
        var monitor = new TemperatureMonitor(-5, 40);
        
        // 订阅事件
        monitor.TemperatureChanged += OnTemperatureChanged;
        monitor.OverheatingDetected += OnOverheatingDetected;
        monitor.FreezingDetected += OnFreezingDetected;
        
        // 模拟温度变化
        Console.WriteLine($"初始温度:{monitor.Temperature}°C ({monitor.Status})");
        
        Console.WriteLine("\n模拟升温到45°C:");
        monitor.SimulateTemperatureChange(45);
        
        Console.WriteLine("\n模拟降温到-10°C:");
        monitor.SimulateTemperatureChange(-10);
        
        Console.WriteLine("\n模拟回到正常温度25°C:");
        monitor.SimulateTemperatureChange(25);
        
        // 文件处理演示
        Console.WriteLine("\n--- 文件处理演示 ---");
        var processor = new FileProcessor();
        
        // 订阅事件
        processor.ProcessingStarted += (sender, e) => 
            Console.WriteLine("开始处理文件...");
            
        processor.FileProcessed += OnFileProcessed;
        
        processor.ProcessingCompleted += (sender, e) => 
        {
            var fp = sender as FileProcessor;
            Console.WriteLine($"\n处理完成!总计:{fp.TotalFiles}个文件,成功:{fp.ProcessedCount}个");
        };
        
        // 创建一些测试文件路径
        string[] testFiles = {
            "test1.txt",
            "test2.txt", 
            "test3.txt",
            "nonexistent.txt",
            "test4.txt"
        };
        
        processor.ProcessFiles(testFiles);
    }
    
    private static void OnTemperatureChanged(object sender, TemperatureChangedEventArgs e)
    {
        var monitor = sender as TemperatureMonitor;
        Console.WriteLine($"温度变化:{e.OldTemperature:F1}°C → {e.NewTemperature:F1}°C " +
                         $"(变化:{e.Change:+0.0;-0.0}°C) [{monitor.Status}]");
    }
    
    private static void OnOverheatingDetected(object sender, EventArgs e)
    {
        Console.WriteLine("⚠️ 警告:检测到过热!");
    }
    
    private static void OnFreezingDetected(object sender, EventArgs e)
    {
        Console.WriteLine("❄️ 警告:检测到过冷!");
    }
    
    private static void OnFileProcessed(object sender, FileProcessedEventArgs e)
    {
        var processor = sender as FileProcessor;
        string status = e.Success ? "✅" : "❌";
        string sizeInfo = e.FileSize > 0 ? $" ({e.FileSize} bytes)" : "";
        string errorInfo = !e.Success && !string.IsNullOrEmpty(e.ErrorMessage) ? $" - {e.ErrorMessage}" : "";
        
        Console.WriteLine($"{status} {e.FileName}{sizeInfo} - {e.ProcessingTime.TotalMilliseconds:F0}ms" +
                         $"{errorInfo} [{processor.Progress:F1}%]");
    }
}

4. 观察者模式实现

4.1 经典观察者模式

// 观察者接口
public interface IObserver<T>
{
    void Update(T data);
}

// 主题接口
public interface ISubject<T>
{
    void Attach(IObserver<T> observer);
    void Detach(IObserver<T> observer);
    void Notify(T data);
}

// 新闻发布者(主题)
public class NewsPublisher : ISubject<string>
{
    private readonly List<IObserver<string>> observers = new List<IObserver<string>>();
    private readonly List<string> news = new List<string>();
    
    public string Name { get; }
    public IReadOnlyList<string> News => news.AsReadOnly();
    
    public NewsPublisher(string name)
    {
        Name = name;
    }
    
    public void Attach(IObserver<string> observer)
    {
        if (observer != null && !observers.Contains(observer))
        {
            observers.Add(observer);
            Console.WriteLine($"订阅者已添加到 {Name},当前订阅者数量:{observers.Count}");
        }
    }
    
    public void Detach(IObserver<string> observer)
    {
        if (observers.Remove(observer))
        {
            Console.WriteLine($"订阅者已从 {Name} 移除,当前订阅者数量:{observers.Count}");
        }
    }
    
    public void Notify(string newsItem)
    {
        Console.WriteLine($"\n{Name} 发布新闻:{newsItem}");
        
        foreach (var observer in observers.ToList()) // 使用ToList避免集合修改异常
        {
            try
            {
                observer.Update(newsItem);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"通知观察者时发生错误:{ex.Message}");
            }
        }
    }
    
    public void PublishNews(string newsItem)
    {
        news.Add(newsItem);
        Notify(newsItem);
    }
    
    public int ObserverCount => observers.Count;
}

// 新闻订阅者(观察者)
public class NewsSubscriber : IObserver<string>
{
    public string Name { get; }
    private readonly List<string> receivedNews = new List<string>();
    
    public IReadOnlyList<string> ReceivedNews => receivedNews.AsReadOnly();
    
    public NewsSubscriber(string name)
    {
        Name = name;
    }
    
    public void Update(string newsItem)
    {
        receivedNews.Add(newsItem);
        Console.WriteLine($"  📰 {Name} 收到新闻:{newsItem}");
    }
    
    public void ShowReceivedNews()
    {
        Console.WriteLine($"\n{Name} 收到的所有新闻 ({receivedNews.Count}条):");
        for (int i = 0; i < receivedNews.Count; i++)
        {
            Console.WriteLine($"  {i + 1}. {receivedNews[i]}");
        }
    }
}

// 智能新闻订阅者(带过滤功能)
public class SmartNewsSubscriber : IObserver<string>
{
    public string Name { get; }
    private readonly List<string> keywords;
    private readonly List<string> filteredNews = new List<string>();
    
    public IReadOnlyList<string> FilteredNews => filteredNews.AsReadOnly();
    
    public SmartNewsSubscriber(string name, params string[] keywords)
    {
        Name = name;
        this.keywords = keywords?.ToList() ?? new List<string>();
    }
    
    public void Update(string newsItem)
    {
        bool isRelevant = keywords.Count == 0 || 
                         keywords.Any(keyword => newsItem.Contains(keyword, StringComparison.OrdinalIgnoreCase));
        
        if (isRelevant)
        {
            filteredNews.Add(newsItem);
            Console.WriteLine($"  🎯 {Name} 收到相关新闻:{newsItem}");
        }
        else
        {
            Console.WriteLine($"  ⏭️ {Name} 过滤了新闻:{newsItem}");
        }
    }
    
    public void AddKeyword(string keyword)
    {
        if (!string.IsNullOrEmpty(keyword) && !keywords.Contains(keyword))
        {
            keywords.Add(keyword);
        }
    }
    
    public void RemoveKeyword(string keyword)
    {
        keywords.Remove(keyword);
    }
    
    public void ShowKeywords()
    {
        Console.WriteLine($"{Name} 的关键词:[{string.Join(", ", keywords)}]");
    }
}

4.2 观察者模式演示

public class ObserverPatternDemo
{
    public static void DemonstrateObserverPattern()
    {
        Console.WriteLine("\n=== 观察者模式演示 ===");
        
        // 创建新闻发布者
        var techNews = new NewsPublisher("科技新闻");
        var sportsNews = new NewsPublisher("体育新闻");
        
        // 创建订阅者
        var generalReader = new NewsSubscriber("普通读者");
        var techEnthusiast = new SmartNewsSubscriber("科技爱好者", "AI", "编程", "科技");
        var sportsLover = new SmartNewsSubscriber("体育爱好者", "足球", "篮球", "比赛");
        var newsCollector = new NewsSubscriber("新闻收集者");
        
        Console.WriteLine("\n--- 订阅设置 ---");
        
        // 订阅科技新闻
        techNews.Attach(generalReader);
        techNews.Attach(techEnthusiast);
        techNews.Attach(newsCollector);
        
        // 订阅体育新闻
        sportsNews.Attach(generalReader);
        sportsNews.Attach(sportsLover);
        sportsNews.Attach(newsCollector);
        
        // 显示关键词
        techEnthusiast.ShowKeywords();
        sportsLover.ShowKeywords();
        
        Console.WriteLine("\n--- 发布新闻 ---");
        
        // 发布科技新闻
        techNews.PublishNews("AI技术在医疗领域取得重大突破");
        techNews.PublishNews("新的编程语言发布,性能提升50%");
        techNews.PublishNews("量子计算机研究获得新进展");
        
        // 发布体育新闻
        sportsNews.PublishNews("世界杯足球赛决赛今晚举行");
        sportsNews.PublishNews("NBA篮球比赛创收视率新高");
        sportsNews.PublishNews("奥运会游泳比赛打破世界纪录");
        
        Console.WriteLine("\n--- 取消部分订阅 ---");
        
        // 普通读者取消科技新闻订阅
        techNews.Detach(generalReader);
        
        // 继续发布新闻
        techNews.PublishNews("区块链技术在金融领域的应用");
        
        Console.WriteLine("\n--- 订阅者收到的新闻统计 ---");
        
        generalReader.ShowReceivedNews();
        
        Console.WriteLine($"\n科技爱好者收到的相关新闻 ({techEnthusiast.FilteredNews.Count}条):");
        for (int i = 0; i < techEnthusiast.FilteredNews.Count; i++)
        {
            Console.WriteLine($"  {i + 1}. {techEnthusiast.FilteredNews[i]}");
        }
        
        Console.WriteLine($"\n体育爱好者收到的相关新闻 ({sportsLover.FilteredNews.Count}条):");
        for (int i = 0; i < sportsLover.FilteredNews.Count; i++)
        {
            Console.WriteLine($"  {i + 1}. {sportsLover.FilteredNews[i]}");
        }
        
        newsCollector.ShowReceivedNews();
        
        Console.WriteLine($"\n发布者统计:");
        Console.WriteLine($"  {techNews.Name}:{techNews.News.Count}条新闻,{techNews.ObserverCount}个订阅者");
        Console.WriteLine($"  {sportsNews.Name}:{sportsNews.News.Count}条新闻,{sportsNews.ObserverCount}个订阅者");
    }
}

5. 总结

本章深入介绍了C#委托和事件的核心概念:

  1. 委托基础:委托的概念、多播委托、内置委托类型
  2. Lambda表达式:表达式语法、变量捕获、函数式编程
  3. 匿名方法:delegate语法、与Lambda的对比
  4. 事件机制:事件定义、事件参数、事件处理
  5. 观察者模式:经典实现、智能订阅、事件驱动架构

关键要点: - 委托是类型安全的函数指针 - 多播委托支持调用链 - Lambda表达式提供简洁的函数式编程语法 - 事件是特殊的委托,提供发布-订阅模式 - 观察者模式实现松耦合的对象通信 - 合理使用事件可以构建响应式系统

下一章预告: 下一章我们将学习LINQ(语言集成查询),包括查询语法、方法语法、延迟执行和自定义LINQ扩展。