重写的List属性调用父类方法?添加元素无效问题求解
问题
以下代码中调用Add方法后无任何效果,最终控制台无输出,原因是每次获取testProp都会返回新的过滤后列表,添加操作只作用于临时列表,未修改父类的底层列表:
internal class TestBase { public virtual List<int> testProp { get; } } internal class Test : TestBase { bool filteringLessThanZeroes = false; public override List<int> testProp { get => base.testProp.Where(i => filteringLessThanZeroes ? i > 0 : i >= 0).ToList(); } } // 调用Add无效果 var test = new Test(); test.testProp.Add(0); test.testProp.Add(23); test.testProp.Add(22); foreach (var item in test.testProp) { Console.WriteLine(item); // 预期输出23、22,实际为空 }
需求:实现获取时过滤元素,但添加元素能生效的逻辑,且同一个属性需根据bool值切换过滤规则,该属性已被大量使用,不想大规模重构。
解决方案
当前思路的核心问题是每次get都返回新列表,导致修改操作无法作用到底层数据。正确的做法是用包装类继承List
完整实现代码
internal class TestBase { public virtual List<int> testProp { get; } public TestBase() { // 父类必须初始化底层列表,避免null引用 testProp = new List<int>(); } } // 自定义过滤列表包装类,继承List<int>以兼容原有代码 internal class FilteredList : List<int> { private readonly List<int> _sourceList; private readonly Func<int, bool> _filter; public FilteredList(List<int> source, Func<int, bool> filter) { _sourceList = source; _filter = filter; } // 修改类方法直接转发到底层列表 public new void Add(int item) => _sourceList.Add(item); public new void Clear() => _sourceList.Clear(); public new bool Remove(int item) => _sourceList.Remove(item); public new void RemoveAt(int index) { var filteredItem = _sourceList.Where(_filter).ElementAt(index); _sourceList.Remove(filteredItem); } // 查询类方法应用过滤逻辑 public new IEnumerator<int> GetEnumerator() => _sourceList.Where(_filter).GetEnumerator(); public new int Count => _sourceList.Count(_filter); public new int this[int index] => _sourceList.Where(_filter).ElementAt(index); public new bool Contains(int item) => _sourceList.Contains(item) && _filter(item); } internal class Test : TestBase { public bool FilteringLessThanZeroes { get; set; } = false; private readonly FilteredList _filteredList; public Test() { // 绑定底层列表和过滤规则 _filteredList = new FilteredList(base.testProp, item => FilteringLessThanZeroes ? item > 0 : item >= 0); } // 返回包装类实例,而非新列表 public override List<int> testProp => _filteredList; } // 测试代码 var test = new Test(); test.testProp.Add(0); test.testProp.Add(23); test.testProp.Add(22); // 默认过滤规则:保留>=0的元素 foreach (var item in test.testProp) { Console.WriteLine(item); // 输出:0、23、22 } // 切换过滤规则:保留>0的元素 test.FilteringLessThanZeroes = true; Console.WriteLine("开启过滤小于0后:"); foreach (var item in test.testProp) { Console.WriteLine(item); // 输出:23、22 }
核心逻辑说明
- 包装类的作用:
FilteredList继承自List<int>,完全兼容原有代码的调用方式,无需修改任何使用testProp的地方。 - 修改操作直接作用底层:
Add、Clear等修改方法直接转发给父类的base.testProp,确保添加/删除操作能持久化到底层数据。 - 查询操作自动过滤:枚举元素、获取
Count、索引器等查询操作会先应用过滤规则,返回符合条件的结果。 - 动态切换过滤规则:修改
FilteringLessThanZeroes属性后,后续的查询操作会自动使用新的过滤条件。
内容的提问来源于stack exchange,提问作者dydx
相关产品推荐
相关产品推荐

