Resharper,foreach循环中的linq

3

Resharper建议使用上面的示例,而不是下面的示例。然而,我认为首先会创建一个新的项目列表,因此在调用runstoredprocedure之前将运行所有_executeFuncs。

通常这不是问题,但异常很容易发生,如果我的假设是正确的,那么尽管函数已经运行,但我的数据库也不会更新?

foreach (var result in rows.Select(row => _executeFunc(row)))
   {                   
      RunStoredProcedure(result)
   }

或者

 foreach(var row in rows)
   {
       var result = _executeFunc(row);
       RunStoredProcedure(result);
   }

_executeFunc 内部也可能会发生异常? - Alexandru
了解延迟执行。 - Hamlet Hakobyan
抱歉,是的,executeFunc(row) 可能会抛出错误。 - McShep
5个回答

4
在您的第一个示例中,_executeFunc(row) 不会在 foreach 循环开始之前为每个 rows 中的项目先调用。 LINQ 将延迟执行。有关详细信息,请参见 此答案
事件顺序如下:
1.评估 rows 中的第一项 2.在该项目上调用 executeFunc(row) 3.调用 RunStoredProcedure(result) 4.重复处理 rows 中的下一项
现在,如果您的代码像这样:
foreach (var result in rows.Select(row => _executeFunc(row)).ToList())
{                   
   RunStoredProcedure(result)
}

因为.ToList()导致集合被枚举,所以它将首先运行LINQ.Select来处理rows中的每个项目。


谢谢大家,你们两位的回答都非常好。真希望我能选择两个回答作为正确答案。不过我选择了 J. Steen 的答案,因为它提供了一个输出示例。 - McShep
没问题,很高兴你找到了答案! - Douglas Barbin

4
在这种情况下,这些语句在语义上与 Select (以及 Linq 通常)使用委托的延迟执行是相同的。 它不会运行任何声明的查询,直到结果被实现,并且根据您编写查询的方式,它将按适当的顺序执行。
以下是一个非常简单的示例:
var list = new List<string>{"hello", "world", "example"};

Func<string, string> func = (s) => {
    Console.WriteLine(s);
    return s.ToUpper();
};

foreach(var item in list.Select(i => func(i)))
{
    Console.WriteLine(item);
}

导致
hello
HELLO
world
WORLD
example
EXAMPLE

3
在上面的例子中,使用Select将逐个投影行,通过yielding它们一行一行地生成。

所以

foreach (var result in rows.Select(row => _executeFunc(row)))

基本上与

foreach(var row in rows)

是一样的。

因此,Select做了类似这样的事情

for each row in source
   result = _executeFunc(row)
   yield result

那个yield表达式在逐行返回每一行(实际上比这更复杂,但是现在这个解释应该足够了)。
如果你使用以下代码
foreach (var result in rows.Select(row => _executeFunc(row)).ToList())
调用ToList()将立即返回一个行的列表,这意味着在你有机会调用RunStoredProcedure()之前,_executeFunc()确实会为每一行调用。
因此,Resharper建议是有效的。公平地说,我相信Jetbrains的开发人员知道他们在做什么 :)

2

Select使用延迟执行。这意味着它将按顺序执行以下操作:

  • rows中获取一个项目
  • 在其上调用_executeFunc
  • _executeFunc的结果上调用RunStoredProcedure

然后它会对下一个项目执行相同的操作,直到列表中的所有项目都被处理完毕。


1
执行将被延迟,这意味着它们将拥有相同的 exec。

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