izb*_*izb 6 c# iterator design-patterns
如果我有以下班级成员:
private List<object> obs;
Run Code Online (Sandbox Code Playgroud)
我希望允许遍历此列表作为类接口的一部分,我该怎么做?
公开它是行不通的,因为我不想直接修改列表.
cas*_*One 13
你会把它暴露为IEnumerable<T>,但不只是直接返回它:
public IEnumerable<object> Objects { get { return obs.Select(o => o); } }
Run Code Online (Sandbox Code Playgroud)
既然您表示只想要遍历列表,那么这就是您所需要的.
人们可能会试图List<object>直接返回IEnumerable<T>,但这是不正确的,因为人们可以IEnumerable<T>在运行时轻松检查,确定它是一个List<T>并将其转换为此类并改变内容.
但是,通过使用return obs.Select(o => o);最终返回迭代器List<object>,而不是直接引用List<object>自身.
根据C#语言规范的第7.15.2.5节,有些人可能会认为这符合"退化表达式".然而,Eric Lippert详细介绍了为什么这个投影没有被优化掉.
此外,人们建议使用AsEnumerable扩展方法.这是不正确的,因为维护了原始列表的引用标识.从文档的备注部分:
AsEnumerable<TSource>(IEnumerable<TSource>)除了将源代码的编译时类型从实现的类型更改IEnumerable<T>为IEnumerable<T>自身之外,该方法没有任何效果.
换句话说,它所做的只是将源参数强制转换为IEnumerable<T>,这无助于保护参照完整性,返回原始引用并可以转换回List<T>并用于改变列表.
| 归档时间: |
|
| 查看次数: |
855 次 |
| 最近记录: |