C#实现继承自List<>的Dimensions类内部Dimension对象变更事件相关问题
现有代码核心问题
- Dimension类Id属性set访问器存在参数错误:Id修改时错误传入了
_Size作为事件参数,无法正确传递Id的变更值 - Dimensions类
OnRemoved方法逻辑错误:错误触发了添加事件的委托,不会触发移除对应的事件 - 缺失单个Dimension对象的属性变更订阅逻辑:添加Dimension对象时没有绑定其内部变更事件,移除时也没有取消订阅,导致对象内部属性修改时Dimensions类无法感知
- 重写List
的Add/Remove方法使用 new关键字存在局限:如果将Dimensions实例转为父类List<Dimension>调用Add/Remove,事件不会触发,建议优先选择继承Collection<Dimension>实现更规范的集合扩展
修正后完整实现代码
namespace Autozite.Entities { // 基础事件参数类,你项目如果已有实现可直接复用 public class xEventArgs<T> : EventArgs { public T Data { get; } public xEventArgs(T data) { Data = data; } } public delegate void DimensionInsideChangeEventHandler(Dimension sender, xEventArgs<int> e); public class Dimension { private int _Id; public int Id { get { return _Id; } set { _Id = value; // 修复参数错误,传递当前修改的Id值 OnChange(new xEventArgs<int>(_Id)); } } private int _Size; public int Size { get { return _Size; } set { _Size = value; OnChange(new xEventArgs<int>(_Size)); } } #region Event On Method public event DimensionInsideChangeEventHandler DimensionChange; protected virtual void OnChange(xEventArgs<int> e) { DimensionChange?.Invoke(this, e); } #endregion } } namespace Autozite.Entities { public delegate void DimensionAddedEventHandler(Dimensions sender, xEventArgs<Dimension> e); public delegate void DimensionRemovedEventHandler(Dimensions sender, xEventArgs<Dimension> e); public delegate void DimensionChangeEventHandler(Dimensions sender, xEventArgs<Dimension> e); // 建议替换为继承Collection<Dimension>,可避免new关键字重写的局限性 public class Dimensions : List<Dimension> { public Dimensions() { } // 实现单个Dimension属性变更的处理逻辑,向上抛出集合层级的事件 private void Dimensions_DimensionChange(Dimension sender, xEventArgs<int> e) { OnChange(new xEventArgs<Dimension>(sender)); } // 修正原委托名称拼写错误 public event DimensionAddedEventHandler DimensionAdded; public event DimensionRemovedEventHandler DimensionRemoved; public event DimensionChangeEventHandler DimensionChange; public new void Add(Dimension dimension) { if (dimension == null) throw new ArgumentNullException(nameof(dimension)); base.Add(dimension); // 添加对象时订阅其内部变更事件 dimension.DimensionChange += Dimensions_DimensionChange; OnAdded(new xEventArgs<Dimension>(dimension)); OnChange(new xEventArgs<Dimension>(dimension)); } public new bool Remove(Dimension dimension) { if (dimension == null) throw new ArgumentNullException(nameof(dimension)); var result = base.Remove(dimension); if (result) { // 移除对象时取消订阅,避免内存泄漏 dimension.DimensionChange -= Dimensions_DimensionChange; OnRemoved(new xEventArgs<Dimension>(dimension)); OnChange(new xEventArgs<Dimension>(dimension)); } return result; } // 补充Clear方法的实现,清空集合时批量取消所有元素的事件订阅 public new void Clear() { foreach (var item in this) { item.DimensionChange -= Dimensions_DimensionChange; } base.Clear(); } #region Event On Method protected virtual void OnAdded(xEventArgs<Dimension> e) { DimensionAdded?.Invoke(this, e); } protected virtual void OnRemoved(xEventArgs<Dimension> e) { // 修复触发错误委托的问题 DimensionRemoved?.Invoke(this, e); } protected virtual void OnChange(xEventArgs<Dimension> e) { DimensionChange?.Invoke(this, e); } #endregion } }
功能验证说明
修改完成后可实现三类变更的统一监听:
- 新增Dimension对象时触发
DimensionAdded和DimensionChange事件 - 移除Dimension对象时触发
DimensionRemoved和DimensionChange事件 - 已添加的Dimension对象内部Id/Size属性修改时触发
DimensionChange事件
内容的提问来源于stack exchange,提问作者Burak Çelebi
相关产品推荐
相关产品推荐

