委托和事件

1. 概述

在C#中,委托(Delegate)和事件(Event)是实现事件驱动编程的重要工具。委托是一种类型安全的函数指针,允许你将方法作为参数传递。事件则是基于委托的,用于实现观察者模式,允许对象在特定事件发生时通知其他对象。

2. 委托(Delegate)

2.1 什么是委托?

委托是一种引用类型,它引用一个或多个方法。你可以将委托看作是一个类型安全的函数指针,它可以指向任何具有相同签名(参数和返回类型)的方法。

2.2 声明委托

委托的声明类似于方法的签名,但使用关键字 delegate。例如:

public delegate void MyDelegate(string message);

这个委托可以指向任何具有 void 返回类型和 string 参数的方法。

2.3 使用委托

你可以创建委托实例并将其指向一个方法,然后调用该委托来执行方法。

public class Program
{
    public static void Main()
    {
        MyDelegate del = new MyDelegate(ShowMessage);
        del("Hello, World!");
    }

    public static void ShowMessage(string message)
    {
        Console.WriteLine(message);
    }
}

2.4 多播委托

委托可以指向多个方法,这种委托称为多播委托。你可以使用 += 运算符将多个方法添加到委托中。

public class Program
{
    public static void Main()
    {
        MyDelegate del = new MyDelegate(ShowMessage);
        del += ShowMessage2;

        del("Hello, World!");
    }

    public static void ShowMessage(string message)
    {
        Console.WriteLine("Message 1: " + message);
    }

    public static void ShowMessage2(string message)
    {
        Console.WriteLine("Message 2: " + message);
    }
}

3. 事件(Event)

3.1 什么是事件?

事件是基于委托的,用于实现观察者模式。事件允许对象在特定事件发生时通知其他对象。事件通常用于GUI编程、异步编程等场景。

3.2 声明事件

事件的声明使用 event 关键字,后面跟着委托类型。例如:

public class Publisher
{
    public delegate void MyEventHandler(string message);
    public event MyEventHandler MyEvent;

    public void RaiseEvent(string message)
    {
        if (MyEvent != null)
        {
            MyEvent(message);
        }
    }
}

3.3 订阅事件

其他类可以订阅事件,并在事件发生时执行特定的方法。

public class Subscriber
{
    public void OnMyEvent(string message)
    {
        Console.WriteLine("Event received: " + message);
    }
}

public class Program
{
    public static void Main()
    {
        Publisher publisher = new Publisher();
        Subscriber subscriber = new Subscriber();

        publisher.MyEvent += subscriber.OnMyEvent;

        publisher.RaiseEvent("Hello, Event!");
    }
}

3.4 取消订阅事件

你可以使用 -= 运算符取消订阅事件。

publisher.MyEvent -= subscriber.OnMyEvent;

4. 实践练习

4.1 练习1:简单的计算器

创建一个简单的计算器程序,使用委托来实现加法、减法、乘法和除法操作。

public delegate double CalculatorDelegate(double x, double y);

public class Calculator
{
    public static double Add(double x, double y) => x + y;
    public static double Subtract(double x, double y) => x - y;
    public static double Multiply(double x, double y) => x * y;
    public static double Divide(double x, double y) => x / y;
}

public class Program
{
    public static void Main()
    {
        CalculatorDelegate calc = new CalculatorDelegate(Calculator.Add);
        Console.WriteLine("Add: " + calc(10, 5));

        calc = Calculator.Subtract;
        Console.WriteLine("Subtract: " + calc(10, 5));

        calc = Calculator.Multiply;
        Console.WriteLine("Multiply: " + calc(10, 5));

        calc = Calculator.Divide;
        Console.WriteLine("Divide: " + calc(10, 5));
    }
}

4.2 练习2:事件驱动的日志系统

创建一个简单的日志系统,使用事件来通知日志记录器记录不同级别的消息(如信息、警告、错误)。

public class Logger
{
    public delegate void LogEventHandler(string message);
    public event LogEventHandler LogEvent;

    public void Log(string message)
    {
        if (LogEvent != null)
        {
            LogEvent(message);
        }
    }
}

public class LogSubscriber
{
    public void OnLogEvent(string message)
    {
        Console.WriteLine("Logged: " + message);
    }
}

public class Program
{
    public static void Main()
    {
        Logger logger = new Logger();
        LogSubscriber subscriber = new LogSubscriber();

        logger.LogEvent += subscriber.OnLogEvent;

        logger.Log("This is an information message.");
        logger.Log("This is a warning message.");
        logger.Log("This is an error message.");
    }
}

5. 总结

委托和事件是C#中实现事件驱动编程的重要工具。委托允许你将方法作为参数传递,而事件则允许对象在特定事件发生时通知其他对象。通过实践练习,你可以更好地理解如何使用委托和事件来构建灵活和可扩展的应用程序。