【问题标题】:IEnumerable multiple enumeration caused by contract precondition合同前置条件导致的IEnumerable多重枚举
【发布时间】:2012-07-04 20:25:15
【问题描述】:

我有一个必须为非空的IEnumerable 参数。如果有像下面这样的先决条件,那么将在此期间枚举集合。但是下次我引用它时会再次枚举,从而在 Resharper 中导致“IEnumerable 的可能多次枚举”警告。

void ProcessOrders(IEnumerable<int> orderIds)
{
    Contract.Requires((orderIds != null) && orderIds.Any());  // enumerates the collection

    // BAD: collection enumerated again
    foreach (var i in orderIds) { /* ... */ }
}

这些变通办法让 Resharper 很高兴,但无法编译:

// enumerating before the precondition causes error "Malformed contract. Found Requires 
orderIds = orderIds.ToList();
Contract.Requires((orderIds != null) && orderIds.Any());
---
// enumerating during the precondition causes the same error
Contract.Requires((orderIds != null) && (orderIds = orderIds.ToList()).Any());

还有其他有效但可能并不总是理想的解决方法,例如使用 ICollection 或 IList,或执行典型的 if-null-throw-exception。

是否有像原始示例中那样适用于代码协定和 IEnumerables 的解决方案?如果没有,那么是否有人开发了一个很好的模式来解决它?

【问题讨论】:

  • 我认为有一个依赖于 IEnumerable 的合同可能只是一个坏主意 - 因为根据定义,IEnumerables 会产生副作用。
  • 到目前为止,我使用 ICollection 作为一种解决方法并且从未遇到过问题,但我很好奇是否有针对 IEnumerables 的解决方案。

标签: c# .net ienumerable validation code-contracts


【解决方案1】:

使用专为IEnumerables 设计的方法之一,例如Contract.Exists

确定元素集合中的元素是否存在于函数中。

退货

当且仅当谓词对集合中任何类型为 T 的元素返回 true 时才为 true。

所以你的谓词可以只返回true


Contract.Requires(orderIds != null);
Contract.Requires(Contract.Exists(orderIds,a=>true));

【讨论】:

  • 这不会也枚举IEnumerable吗?
  • 仅当您 a) 启用了运行时检查,并且 b) 未选择“跳过量词”。 (虽然,在这种情况下,我建议分成两个Requires
  • 嗯,好的。那么说原始代码和您的代码实际上都不会导致枚举(以上面的 a 和 b 为模)是否正确,但是 ReSharper 在原始代码和您的代码中没有意识到这一点只是把它放在 RS 忽略的形式?
  • @Rawling - 正确 - 没有运行时检查,所有调用 Contract 方法的代码都被删除。所以,这只是一种更好地向 Resharper 隐藏它的方法。
  • 感谢您的回答。然而,Resharper 仍然抱怨运行时检查是否打开。知道如何让 Resharper 愉快地接受这一点吗?我已经为每个these instructions 的代码合同添加了一个注释文件,它解决了许多与 RS 的合同问题,但显然它不包括 Contract.Exists。
猜你喜欢
  • 1970-01-01
  • 2014-06-13
  • 2011-04-03
  • 1970-01-01
  • 1970-01-01
  • 2012-01-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多