跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C Sharp 自定义事件访问器
”︁(章节)
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= C#自定义事件访问器 = == 介绍 == 在C#中,'''事件'''是一种特殊的委托类型,用于实现发布-订阅模式。默认情况下,事件使用编译器生成的访问器(add和remove)来管理订阅者。但有时我们需要更精细地控制订阅过程,这时就需要使用'''自定义事件访问器'''。 自定义事件访问器允许开发者: * 控制订阅/取消订阅的逻辑 * 添加线程安全机制 * 实现条件性订阅 * 记录订阅日志 * 执行额外的验证 == 基本语法 == 自定义事件访问器的语法如下: <syntaxhighlight lang="csharp"> event EventHandler MyEvent { add { // 自定义添加订阅者逻辑 } remove { // 自定义移除订阅者逻辑 } } </syntaxhighlight> == 示例:基础实现 == 下面是一个简单的自定义事件访问器示例: <syntaxhighlight lang="csharp"> public class Button { private EventHandler _click; public event EventHandler Click { add { Console.WriteLine($"Adding handler: {value.Method.Name}"); _click += value; } remove { Console.WriteLine($"Removing handler: {value.Method.Name}"); _click -= value; } } public void OnClick() { _click?.Invoke(this, EventArgs.Empty); } } // 使用示例 var button = new Button(); button.Click += (s, e) => Console.WriteLine("Button clicked!"); button.OnClick(); </syntaxhighlight> '''输出:''' <pre> Adding handler: <Main>b__0_0 Button clicked! </pre> == 线程安全实现 == 在多线程环境中,我们需要确保订阅操作的线程安全: <syntaxhighlight lang="csharp"> public class TemperatureSensor { private EventHandler<TemperatureChangedEventArgs> _temperatureChanged; private readonly object _eventLock = new object(); public event EventHandler<TemperatureChangedEventArgs> TemperatureChanged { add { lock (_eventLock) { _temperatureChanged += value; Console.WriteLine($"New subscriber: {value.Method.Name}"); } } remove { lock (_eventLock) { _temperatureChanged -= value; Console.WriteLine($"Removed subscriber: {value.Method.Name}"); } } } public void UpdateTemperature(double newTemp) { var args = new TemperatureChangedEventArgs(newTemp); _temperatureChanged?.Invoke(this, args); } } </syntaxhighlight> == 条件性订阅 == 我们可以通过自定义访问器实现条件性订阅: <syntaxhighlight lang="csharp"> public class AccessControl { private EventHandler _accessGranted; private int _maxSubscribers = 5; private int _currentSubscribers = 0; public event EventHandler AccessGranted { add { if (_currentSubscribers < _maxSubscribers) { _accessGranted += value; _currentSubscribers++; Console.WriteLine("Subscription added"); } else { Console.WriteLine("Maximum subscribers reached"); } } remove { _accessGranted -= value; _currentSubscribers--; Console.WriteLine("Subscription removed"); } } } </syntaxhighlight> == 实际应用案例 == '''场景:'''实现一个股票价格监控系统,当价格变化超过阈值时通知订阅者。 <syntaxhighlight lang="csharp"> public class StockMonitor { private EventHandler<PriceChangedEventArgs> _priceChanged; private decimal _lastPrice; private decimal _threshold = 0.5m; public event EventHandler<PriceChangedEventArgs> PriceChanged { add { // 只允许特定类型的订阅者 if (value.Target is IStockSubscriber) { _priceChanged += value; Console.WriteLine($"Valid subscriber added: {value.Method.Name}"); } else { Console.WriteLine("Invalid subscriber type"); } } remove { _priceChanged -= value; } } public void UpdatePrice(decimal newPrice) { if (Math.Abs(newPrice - _lastPrice) > _threshold) { _priceChanged?.Invoke(this, new PriceChangedEventArgs(_lastPrice, newPrice)); } _lastPrice = newPrice; } } public interface IStockSubscriber { } </syntaxhighlight> == 与自动实现的比较 == <mermaid> graph LR A[事件声明] --> B[自动实现] A --> C[自定义实现] B --> D[编译器生成add/remove] C --> E[完全控制逻辑] C --> F[可添加额外功能] </mermaid> == 性能考虑 == 使用自定义事件访问器时需要注意: * 每次订阅/取消订阅都会执行自定义逻辑 * 锁机制可能影响性能 * 复杂的条件检查会增加开销 == 最佳实践 == 1. 仅在需要额外控制时使用自定义访问器 2. 确保线程安全 3. 保持访问器逻辑简单 4. 避免在访问器中抛出异常 5. 考虑使用显式委托字段而不是自动实现事件 == 数学表达 == 在条件性订阅中,我们可以用数学表达式表示订阅限制: <math> S_{current} < S_{max} \Rightarrow \text{允许订阅} </math> <math> S_{current} \geq S_{max} \Rightarrow \text{拒绝订阅} </math> 其中<math>S_{current}</math>是当前订阅者数量,<math>S_{max}</math>是最大允许订阅者数量。 == 总结 == 自定义事件访问器为C#事件系统提供了强大的扩展能力,使开发者能够: * 精细控制订阅过程 * 实现高级功能如条件订阅和验证 * 增强线程安全性 * 添加日志和监控功能 虽然大多数情况下自动实现的事件已足够,但在需要特殊控制的场景中,自定义事件访问器是不可或缺的工具。 [[Category:编程语言]] [[Category:C Sharp]] [[Category:C Sharp 属性与事件]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)