我遇到了很多情况下收藏被修改了;在函数返回LINQ查询的结果时,枚举操作可能不会执行错误…(我应该添加该函数作为接口的实现,结果将使此模块在另一个中使用.)
Public Function GetTheFuzzyFuzzbuzzes() As IEnumerable(of FuzzBuzz) _ Implements IFoo.GetTheFuzzyFuzzBuzzes Return mySecretDataSource.Where(Function(x) x.IsFuzzy) End Function
作为一个规则,如果底层数据有可能改变,我是否应该在函数或属性getter中返回LINQ查询的结果时一直调用.ToArray?我知道这样做有一点效率,但我觉得这是安全的事情,因此应该总是做到这一点,以避免时间耦合的问题.
编辑:
让我做一个更好的工作来解释问题领域.
我们有一个基于图表的实现我们主要关注的领域,这是一个优化问题.实体被表示为图形节点.用各种成本加权的边缘和其他参数表示节点之间的关系.当用户操纵数据时,我们创建不同的边缘,并评估他们可以对当前状态采取的各种选项,以便为每个选项的结果提供反馈.由其他用户和程序对服务器上的数据进行的更改会通过推送技术立即传播到客户端.我们使用很多线程
所有这些意味着我们以非常异步的方式发生了很多事情.
我们的程序分为模块(基于单一责任原则),具有合同项目和运行时解决的实施项目,这意味着我们严重依赖于接口.我们通常使用IEnumerable在模块之间传递数据(因为它们是不可改变的).
不,我不会这样做的.
我明白你的疑虑主叫方可能不知道这是对查询结果的影响.
有几种情况你真的不能这样做:
>有一些例子,这样做会导致内存不足,例如无限枚举,或在枚举器中产生每次迭代新计算的图像. (我有两个).
>如果您对查询使用Any()或First().两者都只需要阅读第一个元素.所有其他工作都是徒劳的.
>如果您希望Enumerables链接管道/过滤器.实现中间结果只是额外的成本.
另一方面,在许多情况下,将查询实现到数组中是更安全的,当可以想象使用数组将具有影响查询的副作用时.
编写软件时,听起来有吸引力的规则说“当你需要在X和Y之间选择时,总是做X”.我不相信有这样的规则.也许在15%你真的应该做X,在5%你肯定需要做Y,而在其余的情况下,这并不重要.