c#事件委托示例

事件委托的核心概念与编程步骤

事件编程的基本要素,C#事件编程通常包含以下三个核心步骤:
1.定义委托 :约定事件处理方法的签名。
2.声明事件 :基于委托声明一个事件。
3.触发事件:在满足特定条件时调用事件。

在.NET中,标准事件模式通常包含以下组件:

事件委托:通常返回类型为void,并接受两个参数 - object sender(事件源)和派生自EventArgs的参数对象

事件参数:如需传递自定义数据,应创建继承自EventArgs的类

事件触发方法:通常命名为OnEventName,使用protected virtual修饰以便子类可以重写

事件委托示例

  1. 使用自定义委托的基本事件
    以下示例展示了一个简单的角色受伤事件系统:
bash 复制代码
// 定义事件委托
public delegate void DamageEventHandler(int damageAmount);

public class Player
{
    // 声明事件
    public event DamageEventHandler Damaged;
    
    // 触发事件的方法
    public void TakeDamage(int damageAmount)
    {
        OnDamaged(damageAmount);
    }
    
    protected virtual void OnDamaged(int damageAmount)
    {
        // 安全地触发事件(检查是否为null)
        Damaged?.Invoke(damageAmount);
    }
}

// 事件订阅者
public class DamageEffect
{
    public void OnPlayerDamaged(int damageAmount)
    {
        Console.WriteLine($"角色受到 {damageAmount} 点伤害的效果");
    }
}

// 使用示例
class Program
{
    static void Main(string[] args)
    {
        Player player = new Player();
        DamageEffect damageEffect = new DamageEffect();
        
        // 订阅事件
        player.Damaged += damageEffect.OnPlayerDamaged;
        
        // 触发事件
        player.TakeDamage(20);
    }
}
  1. 使用标准EventHandler的温度监控系统
    以下是一个更符合.NET标准的事件实现示例:
bash 复制代码
using System;

// 自定义事件参数(传递数据)
public class TemperatureChangedEventArgs : EventArgs
{
    public double CurrentTemperature { get; }
    public TemperatureChangedEventArgs(double temperature)
    {
        CurrentTemperature = temperature;
    }
}

// 事件发布者
public class TemperatureMonitor
{
    // 使用泛型EventHandler声明事件
    public event EventHandler<TemperatureChangedEventArgs> OnTemperatureExceeded;
    
    private double _threshold;

    public TemperatureMonitor(double threshold)
    {
        _threshold = threshold;
    }

    public void UpdateTemperature(double newTemperature)
    {
        if (newTemperature > _threshold)
        {
            // 触发事件
            OnTemperatureExceeded?.Invoke(this, 
                new TemperatureChangedEventArgs(newTemperature));
        }
    }
}

// 事件订阅者
public class AlertSystem
{
    public AlertSystem(TemperatureMonitor monitor)
    {
        // 订阅事件
        monitor.OnTemperatureExceeded += HandleOverheat;
    }

    private void HandleOverheat(object sender, TemperatureChangedEventArgs e)
    {
        Console.WriteLine($"警报:温度超标!当前温度 {e.CurrentTemperature}°C");
    }
}

// 使用示例
class Program
{
    static void Main()
    {
        var monitor = new TemperatureMonitor(100); // 阈值设为100°C
        var alert = new AlertSystem(monitor);
        
        monitor.UpdateTemperature(99);  // 不会触发
        monitor.UpdateTemperature(105); // 触发事件,输出警报
    }
}
  1. 杂志订阅发布系统(多事件示例)
    以下示例展示了包含多个事件和自定义事件参数的复杂场景:
bash 复制代码
using System;

// 自定义事件参数
public class PubEventArgs : EventArgs
{
    public string MagazineName { get; }
    public string PublishDate { get; }
    
    public PubEventArgs(string magazineName, DateTime pubDate)
    {
        MagazineName = magazineName;
        PublishDate = pubDate.ToString("yyyy-MM-dd");
    }
}

// 发布者类
public class Publisher
{
    // 声明多个事件
    public event EventHandler<PubEventArgs> PubComputer;
    public event EventHandler<PubEventArgs> PubLife;
    
    protected virtual void OnPubComputer(PubEventArgs e)
    {
        PubComputer?.Invoke(this, e);
    }
    
    protected virtual void OnPubLife(PubEventArgs e)
    {
        PubLife?.Invoke(this, e);
    }
    
    public void IssueComputer(string magazineName, DateTime pubDate)
    {
        Console.WriteLine($"发行{magazineName}");
        OnPubComputer(new PubEventArgs(magazineName, pubDate));
    }
    
    public void IssueLife(string magazineName, DateTime pubDate)
    {
        Console.WriteLine($"发行{magazineName}");
        OnPubLife(new PubEventArgs(magazineName, pubDate));
    }
}

// 订阅者类
public class Subscriber
{
    private string _name;
    
    public Subscriber(string name)
    {
        _name = name;
    }
    
    public void Receive(object sender, PubEventArgs e)
    {
        Console.WriteLine($"{e.PublishDate} {_name}已经收到{e.MagazineName}");
    }
}

总结 事件与委托的关系:

事件是特殊的委托,它提供了更好的封装性,防止外部类直接触发事件

安全的事件触发模式:使用?.Invoke()可以安全地触发事件,避免空引用异常

事件订阅与取消:使用+=操作符订阅事件,使用-=操作符取消订阅

标准事件模式的重要性:遵循.NET框架的事件模式(使用EventHandler和EventArgs)可以提高代码的一致性和可维护性

典型应用场景:事件委托广泛应用于用户界面交互、异步操作通知、传感器数据监控和游戏状态变化等场景

相关推荐
后端小张3 小时前
【JAVA 进阶】穿越之我在修仙世界学习 @Async 注解(深度解析)
java·开发语言·spring boot·后端·spring·注解·原理
用户3721574261353 小时前
C# 实现在 Excel 中高效生成和操作表格
c#
Yeats_Liao3 小时前
Go Web 编程快速入门 18 - 附录B:查询与扫描
开发语言·前端·后端·golang
国服第二切图仔3 小时前
Rust实战开发之图形界面开发入门(egui crate)
开发语言·后端·rust
Zhangzy@3 小时前
Rust 依赖管理与版本控制
开发语言·后端·rust
Momentary_SixthSense3 小时前
rust表格文件处理
开发语言·rust
小八四爱吃甜食3 小时前
【R语言】构建GO、KEGG相关不同物种的R包
开发语言·golang·r语言
音符犹如代码3 小时前
ArrayList常见面试题二
java·开发语言·面试·职场和发展
csdn_aspnet3 小时前
C# 金字塔体积计算程序(Program for volume of Pyramid)
c#