在我的代码中,我需要多次使用IEnumerable<>,导致"可能多次枚举IEnumerable"的ReSharper错误.

示例代码:

public List<object> Foo(IEnumerable<object> objects)
{
    if (objects == null || !objects.Any())
        throw new ArgumentException();
        
    var firstObject = objects.First();
    var list = DoSomeThing(firstObject);        
    var secondList = DoSomeThingElse(objects);
    list.AddRange(secondList);
    
    return list;
}
  • 我可以将objects参数更改为List,然后避免可能的多重枚举,但这样我就无法得到我能处理的最高对象.
  • 我可以做的另一件事是在方法的开头将IEnumerable转换为List:

 public List<object> Foo(IEnumerable<object> objects)
 {
    var objectList = objects.ToList();
    // ...
 }

但这只是awkward.

在这种情况下你会怎么做?

推荐答案

IEnumerable作为参数的问题是,它告诉呼叫者"我想列举这个".它不会告诉他们你想列举多少次.

我可以将objects参数更改为List,然后避免可能的多重枚举,但这样就不会得到the highest object that I can handle.

追求最高的目标是高尚的,但它为太多的假设留下了空间.您真的希望有人将LINQ to SQL查询传递给这个方法,只让您枚举两次(每次都可能得到不同的结果?)

这里缺少的语义是,调用者可能不会花时间阅读方法的细节,可能会假设您只迭代一次,因此他们会向您传递一个昂贵的对象.你的方法签名没有指明任何一种方式.

通过将方法签名更改为IList/ICollection,您至少可以让调用者更清楚地了解您的期望,并且可以避免代价高昂的错误.

否则,大多数研究该方法的开发人员可能会认为您只迭代一次.如果采取IEnumerable是非常重要的,你应该考虑在方法开始时做.ToList().

遗憾的是,.NET没有IEnumerable+Count+Indexer的接口,没有Add/Remove等方法,我怀疑这会解决这个问题.

.net相关问答推荐

.NET Blazor-使用子组件中的处理程序方法进行双向数据绑定

从没有流的EventStore中读取流不存在异常

Blazor服务器应用程序需要在页面上点击才能与元素交互

保存时不保留 XML 格式

为什么 GetShortestDayName 返回的名称比预期的短?

什么是表达式树,如何使用它们,为什么要使用它们?

lock() 是否保证按请求的顺序获得?

从 switch 块中跳出 foreach 循环

log4net 与 TraceSource

如何使用c#从excel文件中读取数据

.net 服务总线建议?

如何让 .NET 的 Path.Combine 将正斜杠转换为反斜杠?

软件包版本始终为 1.0.0,带有 dotnet pack

是否有可用的 WPF 备忘单?

多个添加的实体可能具有相同的主键

一个接口是否应该继承另一个接口

在 .NET 中获取默认打印机的最佳方法是什么

无锁多线程适用于真正的线程专家

如何获取当前的 ProcessID?

记录器包装器最佳实践