总目录
C# 语法总目录
系列链接
C#语言进阶(二) 事件 第一篇(发布订阅模式)
C#语言进阶(二) 事件 第二篇(.net标准事件模型)
C#语言进阶(二) 事件 第二篇(事件访问器)
事件 第三篇目录
-
- [事件 第三篇](#事件 第三篇)
-
- [3. 事件访问器](#3. 事件访问器)
事件 第三篇
3. 事件访问器
默认情况下,编译器会默认实现事件的访问器,如果显示的去实现,那么编译器就不会自动取生成默认的访问器。
从功能上,自己手动写访问器和编译器默认生成是一样的,但是编译器默认生成的使用了无锁的比较并交换算法,保证在更新委托时的线程安全性,在多线程情况下更安全些。
一般情况不需要自己去显示写事件访问器,如果需要更多高级操作,那么就不得不用。
以下是一些可能需要用的情况 (当然也可以不用):
- 当事件很多,订阅者却不多,这种情况下需要自定义访问器的add方法,在方法里使用字典来存储委托引用,这样比原来的开销小
- 当广播类继承了多个事件接口,并且有多个接口的事件名称是相同的,那么需要把这些接口的事件显示的去创建访问器,用来区分它们用哪个访问器访问
含有相同事件的接口
csharp
public interface IMathScore
{
event EventHandler<ScoreChangedCusEventArgs> ScoreChanged;
}
public interface IEnglishScore
{
event EventHandler<ScoreChangedCusEventArgs> ScoreChanged;
}
标准事件参数类
csharp
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;
}
}
发布者类
csharp
//发布者
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);
}
}
}
订阅者类
csharp
//订阅者
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);
}
}
订阅者类
csharp
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);
}
}
输出
csharp
//输出
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#语言进阶(二) 事件 第二篇(事件访问器)