位置: 文档库 > C#(.NET) > 文档下载预览

《 C# 知识回顾 - 事件入门.doc》

1. 下载的文档为doc格式,下载后可用word或者wps进行编辑;

2. 将本文以doc文档格式下载到电脑,方便收藏和打印;

3. 下载后的文档,内容与下面显示的完全一致,下载之前请确认下面内容是否您想要的,是否完整.

点击下载文档

C# 知识回顾 - 事件入门.doc

《C# 知识回顾 - 事件入门》

在C#编程中,事件(Event)是面向对象编程中实现“发布-订阅”模式的核心机制。它允许对象之间通过消息传递进行松耦合通信,是构建响应式应用程序(如GUI界面、异步任务处理等)的基础。本文将从基础概念出发,结合代码示例,系统梳理事件的定义、声明、触发与订阅的全流程,帮助开发者快速掌握这一关键特性。

一、事件的核心概念

事件本质上是委托(Delegate)的特殊应用,用于在特定条件满足时通知订阅者。其核心包含三个角色:

  • 发布者(Publisher):触发事件的类,通常包含事件声明和触发逻辑。
  • 订阅者(Subscriber):响应事件的类,通过方法订阅事件。
  • 事件参数(EventArgs):携带事件相关数据的类,继承自System.EventArgs

与直接调用方法不同,事件允许发布者在不了解订阅者具体实现的情况下通知多个对象,实现“一对多”的通信模式。

二、声明与触发事件

1. 定义事件

事件需基于委托类型声明。首先定义委托,再声明事件:

// 1. 定义委托(可复用)
public delegate void NotifyHandler(string message);

// 2. 发布者类中声明事件
public class Publisher
{
    // 声明事件(private修饰符限制外部直接触发)
    public event NotifyHandler OnNotify;

    // 触发事件的方法
    public void DoSomething()
    {
        Console.WriteLine("Publisher is working...");
        // 检查是否有订阅者(避免null引用异常)
        OnNotify?.Invoke("Task completed!");
    }
}

2. 自定义事件参数

当需要传递额外数据时,可创建自定义EventArgs类:

// 自定义事件参数类
public class CustomEventArgs : EventArgs
{
    public string Data { get; }
    public int Code { get; }

    public CustomEventArgs(string data, int code)
    {
        Data = data;
        Code = code;
    }
}

// 更新委托与事件
public delegate void CustomNotifyHandler(object sender, CustomEventArgs e);

public class AdvancedPublisher
{
    public event CustomNotifyHandler OnCustomNotify;

    public void TriggerEvent()
    {
        OnCustomNotify?.Invoke(this, new CustomEventArgs("Error", 500));
    }
}

三、订阅与处理事件

订阅者通过“+=”操作符将方法绑定到事件,并在事件触发时执行:

public class Subscriber
{
    public void Subscribe(Publisher publisher)
    {
        // 订阅事件
        publisher.OnNotify += HandleNotification;
    }

    // 事件处理方法
    private void HandleNotification(string message)
    {
        Console.WriteLine($"Subscriber received: {message}");
    }

    // 取消订阅(避免内存泄漏)
    public void Unsubscribe(Publisher publisher)
    {
        publisher.OnNotify -= HandleNotification;
    }
}

完整示例:

var publisher = new Publisher();
var subscriber = new Subscriber();

// 订阅
subscriber.Subscribe(publisher);
publisher.DoSomething(); // 输出:Subscriber received: Task completed!

// 取消订阅
subscriber.Unsubscribe(publisher);
publisher.DoSomething(); // 无输出

四、事件的高级用法

1. 静态事件

静态事件属于类而非实例,适用于全局通知场景:

public static class GlobalNotifier
{
    public static event Action OnGlobalEvent;

    public static void RaiseGlobalEvent()
    {
        OnGlobalEvent?.Invoke("System alert!");
    }
}

// 订阅
GlobalNotifier.OnGlobalEvent += msg => Console.WriteLine(msg);
GlobalNotifier.RaiseGlobalEvent(); // 输出:System alert!

2. 异步事件处理

使用async方法处理耗时操作,避免阻塞事件触发:

public class AsyncPublisher
{
    public event Action OnAsyncEvent;

    public async Task TriggerAsync()
    {
        await Task.Delay(1000); // 模拟耗时操作
        OnAsyncEvent?.Invoke();
    }
}

public class AsyncSubscriber
{
    public async Task HandleAsync()
    {
        await Task.Run(() => 
        {
            Console.WriteLine("Async processing started...");
            Thread.Sleep(2000);
            Console.WriteLine("Async processing completed!");
        });
    }
}

// 使用
var publisher = new AsyncPublisher();
var subscriber = new AsyncSubscriber();
publisher.OnAsyncEvent += () => subscriber.HandleAsync().Wait();
await publisher.TriggerAsync();

3. 弱事件模式(Weak Event)

避免订阅者对象被事件持有导致内存泄漏,可通过WeakReference或第三方库(如Prism)实现:

// 简化版弱事件实现
public class WeakEventManager
{
    private List> _handlers = new List>();

    public void AddHandler(Action handler)
    {
        _handlers.Add(new WeakReference(handler));
    }

    public void Raise()
    {
        foreach (var weakRef in _handlers)
        {
            if (weakRef.TryGetTarget(out var handler))
            {
                handler?.Invoke();
            }
        }
    }
}

五、事件与委托的区别

事件是委托的封装,主要区别如下:

特性 委托(Delegate) 事件(Event)
访问修饰符 通常为public 外部只能订阅/取消订阅,不能直接触发
线程安全 需手动处理多线程问题 内置线程安全检查
使用场景 回调、多播委托 发布-订阅模式、GUI事件

六、最佳实践与注意事项

  1. 命名规范:事件名以“On”开头(如OnValueChanged),处理方法以“Handler”结尾(如ValueChangedHandler)。
  2. 空检查:触发事件前使用?.Invoke避免NullReferenceException
  3. 取消订阅:在订阅者销毁时取消订阅,防止内存泄漏。
  4. 避免阻塞:事件处理方法中避免长时间运行操作,考虑使用异步模式。
  5. 线程安全:多线程环境下使用lockConcurrentDictionary保护事件列表。

七、实际应用场景

1. WinForms/WPF中的按钮点击事件

// WinForms示例
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        button1.Click += Button1_Click; // 订阅点击事件
    }

    private void Button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show("Button clicked!");
    }
}

2. MVVM模式中的属性变更通知

public class ViewModel : INotifyPropertyChanged
{
    private string _name;
    public string Name
    {
        get => _name;
        set
        {
            _name = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

3. 观察者模式实现

public interface IObserver
{
    void Update(string message);
}

public class Observer : IObserver
{
    public void Update(string message)
    {
        Console.WriteLine($"Observer received: {message}");
    }
}

public class Subject
{
    private List _observers = new List();

    public event Action OnUpdate; // 或直接使用委托

    public void Attach(IObserver observer)
    {
        OnUpdate += observer.Update;
        // _observers.Add(observer); // 传统观察者模式实现
    }

    public void Notify(string message)
    {
        OnUpdate?.Invoke(message);
        // foreach (var obs in _observers) obs.Update(message);
    }
}

关键词:C#事件、委托、发布-订阅模式、EventArgs、异步事件、弱事件、MVVM、观察者模式

简介:本文系统讲解C#事件机制,从基础概念到高级用法,涵盖事件声明、触发、订阅全流程,结合代码示例说明自定义事件参数、异步处理、弱事件模式等核心技巧,并对比事件与委托的区别,提供WinForms、MVVM等实际场景的应用指南,适合C#开发者巩固事件编程能力。

《 C# 知识回顾 - 事件入门.doc》
将本文以doc文档格式下载到电脑,方便收藏和打印
推荐度:
点击下载文档