如何阻止字段回调意外触发?C#属性回调异常问题求助
问题解析与解决方案
首先,咱们来拆解你遇到的问题:你原以为在清空集合后第一次调用Add时不会触发回调,但实际上它触发了,而第二次Add却没有。这背后的核心原因是List是引用类型,每次你访问origFileList属性(哪怕是调用它的Add方法),都会先执行属性的getter逻辑。
为什么会出现这个现象?
咱们一步一步看执行流程:
- 当你执行
CollectionHandler.origFileList.RemoveAt(0)后,_origFileList的Count变成0。 - 接下来执行
CollectionHandler.origFileList.Add("Test Value #1"):- 第一步:调用
origFileList的getter,此时_origFileList.Count是0,满足<1的条件,所以触发myTestCallback(),输出那行提示。 - 第二步:getter返回
_origFileList的实例。 - 第三步:调用这个实例的
Add方法,把元素加入集合,此时Count变成1。
- 第一步:调用
- 第二次执行
Add时,_origFileList.Count已经是1,getter里的条件不满足,所以不会触发回调。
简单来说:你触发回调的时机是每次访问属性的时候,而不是集合状态真正变为空的时刻——哪怕你是要往空集合里加元素,只要先访问了属性,回调就会先执行。
如何修复?
根据你的设计意图(设置属性不触发回调,仅在检查字段值满足条件时触发),最佳方案是不要直接暴露List类型的属性,而是封装集合的操作方法,把回调触发逻辑放到集合状态变化后的检查中,或者提供专门的检查方法。
这里给你一个修改后的实现:
using System.Collections.Generic; using System; public static class CollectionHandler { // 保持私有,不直接暴露 private static List<string> _origFileList = new List<string>(); // 封装添加操作 public static void AddOrigFile(string value) { _origFileList.Add(value); // 添加后集合不会为空,无需触发回调 } // 封装删除操作 public static void RemoveOrigFileAt(int index) { if (index >= 0 && index < _origFileList.Count) { _origFileList.RemoveAt(index); // 删除后检查是否为空,为空则触发回调 CheckIfEmptyAndTriggerCallback(); } } // 提供只读的集合访问,避免外部直接修改 public static IReadOnlyList<string> GetOrigFileList() { return _origFileList.AsReadOnly(); } // 专门的检查方法,按需触发回调 public static void CheckIfEmptyAndTriggerCallback() { if (_origFileList.Count < 1) { myTestCallback(); } } private static void myTestCallback() { Console.WriteLine("origFileList - Is now empty"); } } // 调用示例 CollectionHandler.AddOrigFile("Value 1"); CollectionHandler.AddOrigFile("Value 2"); CollectionHandler.RemoveOrigFileAt(1); CollectionHandler.RemoveOrigFileAt(0); // 删除后为空,触发回调 // Output> origFileList - Is now empty CollectionHandler.AddOrigFile("Test Value #1 - Should not fire the callback !!!"); // 无输出,符合预期 CollectionHandler.AddOrigFile("Test Value #2 - Should not fire the callback ---"); // 无输出,符合预期
这个实现的优势在于:
- 完全控制集合的修改路径,避免外部直接操作List导致的意外触发。
- 回调只会在集合真正变为空的时刻(删除操作后)触发,添加元素时不会触发,完全符合你的设计意图。
- 通过
IReadOnlyList提供只读访问,保证集合的安全性。
内容的提问来源于stack exchange,提问作者Rick Riggs
相关产品推荐
相关产品推荐

