一尘不染

处理可能的IEnumerable多个枚举的警告

c#

在我的代码中需要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,然后避免可能的多重枚举,但是我没有得到可以处理的最高对象。
  • 另一件事,我可以做的就是将转换IEnumerableList在方法的开头:

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

但是,这很 尴尬

在这种情况下您会做什么?


阅读 225

收藏
2020-05-19

共1个答案

一尘不染

IEnumerable使用参数作为问题是它告诉调用者“我希望枚举”。它不会告诉他们您希望枚举多少次。

我可以将objects参数更改为List,然后避免可能的多重枚举,但是我没有得到 我能处理的最高对象

追求最高目标的目标是崇高的,但它为太多的假设留有余地。您是否真的要有人将LINQ to
SQL查询传递给此方法,而只让您枚举两次(每次都可能得到不同的结果?)。

这里缺少的语义是,调用者可能不花时间来阅读方法的详细信息,因此可能会假设您仅迭代一次-因此,它们将为您传递一个昂贵的对象。您的方法签名不指示任何一种方式。

通过将方法签名更改为IList/ ICollection,至少可以使调用者更清楚自己的期望,并且它们可以避免代价高昂的错误。

否则,大多数使用该方法的开发人员可能会假设您仅迭代一次。如果采用IEnumerable是如此重要,则应.ToList()在方法开始时考虑进行。

真可惜.NET没有IEnumerable + Count + Indexer接口,没有Add / Remove等方法,这是我怀疑可以解决此问题的方法。

2020-05-19