C#语言进阶(二)—事件 第三篇(事件访问器)

总目录
C# 语法总目录

系列链接
C#语言进阶(二)    事件 第一篇(发布订阅模式)
C#语言进阶(二)    事件 第二篇(.net标准事件模型)
C#语言进阶(二)    事件 第二篇(事件访问器)

事件 第三篇目录

事件 第三篇

3. 事件访问器

  默认情况下,编译器会默认实现事件的访问器,如果显示的去实现,那么编译器就不会自动取生成默认的访问器。

  从功能上,自己手动写访问器和编译器默认生成是一样的,但是编译器默认生成的使用了无锁的比较并交换算法,保证在更新委托时的线程安全性,在多线程情况下更安全些。

  一般情况不需要自己去显示写事件访问器,如果需要更多高级操作,那么就不得不用。

以下是一些可能需要用的情况 (当然也可以不用):

  • 当事件很多,订阅者却不多,这种情况下需要自定义访问器的add方法,在方法里使用字典来存储委托引用,这样比原来的开销小
  • 当广播类继承了多个事件接口,并且有多个接口的事件名称是相同的,那么需要把这些接口的事件显示的去创建访问器,用来区分它们用哪个访问器访问

含有相同事件的接口

public interface IMathScore
{
    event EventHandler<ScoreChangedCusEventArgs> ScoreChanged;
}
public interface IEnglishScore
{
    event EventHandler<ScoreChangedCusEventArgs> ScoreChanged;
}

标准事件参数类

public class ScoreChangedCusEventArgs : EventArgs
{
    public static readonly new ScoreChangedCusEventArgs? Empty;
    //通常标准事件模型传递的参数设置为只读类型
    public readonly decimal oldScore;
    public readonly decimal newScore;
    public ScoreChangedCusEventArgs(decimal oldScore, decimal newScore)
    {
        this.oldScore = oldScore;
        this.newScore = newScore;
    }
}

发布者类

//发布者
public class BroadCasterCusStandar:IMathScore,IEnglishScore
{
    private string? name;
    private decimal englishScore;
    private decimal mathScore;

    event EventHandler<ScoreChangedCusEventArgs> MathEvent;
    event EventHandler<ScoreChangedCusEventArgs> EnglishEvent;

    object objectLock = new Object();

    event EventHandler<ScoreChangedCusEventArgs>? IMathScore.ScoreChanged
    {
        add {
            lock (objectLock)
            {
                MathEvent += value;
            }
        }
        remove {
            lock (objectLock)
            {
                MathEvent -= value;
            }
        }
    }

    event EventHandler<ScoreChangedCusEventArgs>? IEnglishScore.ScoreChanged
    {
        add
        {
            lock (objectLock)
            {
                EnglishEvent += value;
            }
        }
        remove
        {
            lock (objectLock)
            {
                EnglishEvent -= value;
            }
        }
    }

    protected virtual void OnMathScoreChanged(ScoreChangedCusEventArgs? e)
    {
        MathEvent?.Invoke(this, e);
    }
    protected virtual void OnEnglishScoreChanged(ScoreChangedCusEventArgs? e)
    {
        EnglishEvent?.Invoke(this, e);
    }

    public BroadCasterCusStandar(string name)
    {
        this.name = name;
    }
    public decimal MathScore
    {
        get { return mathScore; }
        set
        {
            if (mathScore == value) return;
            decimal oldMathScore = mathScore;
            mathScore = value;

            OnMathScoreChanged(new ScoreChangedCusEventArgs(oldMathScore, mathScore));
            //如果不需要传值,那么可以用下面代替
            //OnMathScoreChanged(ScoreChangedCusEventArgs.Empty);
        }
    }

    public decimal EnglishScore
    {
        get { return englishScore; }
        set
        {
            if (englishScore == value) return;
            decimal oldEnglishScore = englishScore;
            englishScore = value;

            OnEnglishScoreChanged(new ScoreChangedCusEventArgs(oldEnglishScore, englishScore));
            //如果不需要传值,那么可以用下面代替
            //OnEnglishScoreChanged(ScoreChangedCusEventArgs.Empty);
        }
    }
}

订阅者类

//订阅者
internal class SubscriberCus1Standar
{
    private readonly string _id;
    public SubscriberCus1Standar(string id, BroadCasterCusStandar broad)
    {
        _id = id;
        IEnglishScore englishBroad = (IEnglishScore)broad;
        //订阅信息
        englishBroad.ScoreChanged += ScoreChanged;
    }

    //处理广播信息
    void ScoreChanged(object? obj, ScoreChangedCusEventArgs e)
    {
        if (e == ScoreChangedCusEventArgs.Empty)
        {
            return;
        }
        Console.WriteLine("this id is: " + _id + ",  oldscore is " + e.oldScore + "  ,new Score is: " + e.newScore + "  ,time is: " + DateTime.Now);
    }
}

订阅者类

internal class SubscriberCus2Standar
{
    private readonly string _id;
    public SubscriberCus2Standar(string id, BroadCasterCusStandar broad)
    {
        _id = id;
        IMathScore englishBroad = (IMathScore)broad;
        //订阅信息
        englishBroad.ScoreChanged += ScoreChanged;
    }

    //处理广播信息
    void ScoreChanged(object? obj, ScoreChangedCusEventArgs e)
    {
        if (e == ScoreChangedCusEventArgs.Empty)
        {
            return;
        }
        Console.WriteLine("this id is: " + _id + ",  oldscore is " + e.oldScore + "  ,new Score is: " + e.newScore + "  ,time is: " + DateTime.Now);
    }
}

输出

//输出
this id is: 02,  oldscore is 0  ,new Score is: 15  ,time is: 2000/1/1 17:34:35
this id is: 01,  oldscore is 0  ,new Score is: 20  ,time is: 2000/1/1 17:34:35 

总目录
C# 语法总目录

系列链接
C#语言进阶(二)    事件 第一篇(发布订阅模式)
C#语言进阶(二)    事件 第二篇(.net标准事件模型)
C#语言进阶(二)    事件 第二篇(事件访问器)

相关推荐

  1. C#语言()—事件 (事件访问)

    2024-06-06 17:38:02       35 阅读
  2. C#语言()—事件 第二(.net标准事件模型)

    2024-06-06 17:38:02       32 阅读
  3. C#语言()—事件 第二(.net标准事件模型)

    2024-06-06 17:38:02       35 阅读
  4. C++事件聚合

    2024-06-06 17:38:02       33 阅读
  5. C#基础语法( 委托与事件

    2024-06-06 17:38:02       55 阅读
  6. C#语言() 元组

    2024-06-06 17:38:02       38 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-06 17:38:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-06 17:38:02       101 阅读
  3. 在Django里面运行非项目文件

    2024-06-06 17:38:02       82 阅读
  4. Python语言-面向对象

    2024-06-06 17:38:02       91 阅读

热门阅读

  1. WebRTC 在 iOS 端实现一对一通信

    2024-06-06 17:38:02       26 阅读
  2. 【OpenCV】基于opencv的视频间隔抽帧脚本

    2024-06-06 17:38:02       41 阅读
  3. HarmonyOS LocalStorage使用

    2024-06-06 17:38:02       31 阅读
  4. ceph报错整理

    2024-06-06 17:38:02       34 阅读
  5. Debian12安装K8S

    2024-06-06 17:38:02       28 阅读
  6. Linux 环境搭建与常用命令指南

    2024-06-06 17:38:02       29 阅读
  7. [docker] docker-compose-redis.yml

    2024-06-06 17:38:02       32 阅读
  8. 风控场景下文本分类-实战

    2024-06-06 17:38:02       34 阅读