这是一种安全的修复方法,用于解决“可能对IEnumerable进行多次枚举”的问题。

3
我目前有这个:

我现在有这个:

public void Load(IEnumerable<Guid> ids){
    f1(ids);
    f2(ids);
} 

为了避免Resharper的波浪线提示,建议修复方法如下:
public void Load(IEnumerable<Guid> ids){
    var enumerable = ids as IList<Guid> ?? ids.ToList();
    f1(enumerable);
    f2(enumerable);
} 

问题是我总是想不出一个好的名称来表示“可枚举”,我不想称其为idsList或enumeratedIds,而enumerable也肯定行不通,而ids已经用于参数。因此,我的实际问题是这样做是否能解决这两个问题?

public void Load(IEnumerable<Guid> ids){
    ids = ids as IList<Guid> ?? ids.ToList();
    f1(ids);
    f2(ids);
}

以上情况是否存在意料之外的/低效的结果?


3
你在担心方法名字像 f1f2 这样的变量名吗? - Tim Schmelter
1
看起来这是一个重复的问题:处理可能多次枚举IEnumerable的警告 - harley.333
如果在枚举到下一个集合时尝试使用某个内容更新/删除该集合,则会出现问题。 - 123 456 789 0
讽刺的是,我也想不出任何好的函数名称。我想这是我的一个弱点。 - Eric B
2
如果你需要一个列表,就拿一个列表,没什么好说的。如果你最终还是要进行类型转换,为什么不一开始就直接使用列表呢? - Ed S.
2个回答

4
以下情况可能会导致上述方法产生意外或效率低下的结果吗?
如果既不是f1也不是f2枚举整个Guid列表,并且ids不作为List< Guid >给出,则转换为列表的成本更高。例如,当f1取前五个元素,f2取FirstOrDefault,ids来自非缓存上下文并且包含数千个项时,ToList方法的效率将会降低。
为避免Resharper波浪线,建议的解决方法是...
并非所有Resharper警告都必须修复。该工具会引起您对问题的关注,但是修复它还是忽略警告由您决定。Resharper始终注意潜在问题,但只有您知道f1和f2内部发生了什么。如果您认为避免实例化列表更有效,请使用// ReSharper disable注释以避免波浪线。

2

如果您正在使用具有延迟执行实体集合的Entity Framework,则这可能是一个非常糟糕的做法!想象一下,如果您的ids IEnumerable实际上是由类似以下内容定义的:

var ids = MyDbContext.BillionsOfAccounts.Select(x => x.id);

而你的函数可能是像这样的(这可能不会编译,但可以传达要点):
public IEnumerable<T> f1(IEnumerable<T> query)
{
  if (query is IQueryable<T>)
  {
    return query.Take(10).ToList();
  }
  return null;
}

public IEnumerable<T> f2(IEnumerable<T> query)
{
  if (query is IQueryable<T>)
  {
    return query.Where(id => (id % 100000000) == 0).ToList();
  }
  return null;
}

如果是这种情况,那么你所做的可能会尝试从数据库中获取数十亿条记录,而不是原本想要的10条记录。
话虽如此,有很多情况下你所尝试的确实是你想要的。正如其他人所说,你必须按情况处理。但回答你的问题,是的,有一些场景这可能非常糟糕!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接