Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用LINQ时谓词的顺序重要吗?_C#_.net_Performance_Linq_Optimization - Fatal编程技术网

C# 使用LINQ时谓词的顺序重要吗?

C# 使用LINQ时谓词的顺序重要吗?,c#,.net,performance,linq,optimization,C#,.net,Performance,Linq,Optimization,我理解以不同的顺序执行操作将产生不同的性能,例如以下慢速查询之间的差异: List<TestItem> slowResults = items.OrderBy(item => item.StringItem) .Where(item => item.IntItem == 100) .ToList(); List slowResults=

我理解以不同的顺序执行操作将产生不同的性能,例如以下慢速查询之间的差异:

List<TestItem> slowResults = items.OrderBy(item => item.StringItem)
                                  .Where(item => item.IntItem == 100)
                                  .ToList();
List slowResults=items.OrderBy(item=>item.StringItem)
.其中(item=>item.IntItem==100)
.ToList();
还有这个更快的:

List<TestItem> fastResults = items.Where(item => item.IntItem == 100)
                                  .OrderBy(item => item.StringItem)
                                  .ToList();
List fastResults=items.Where(item=>item.IntItem==100)
.OrderBy(item=>item.StringItem)
.ToList();
但这不是我的问题:

我的问题是关于短路的性能,因为它和LINQ谓词有关。当我使用Where子句时,如本例所示:

List<TestItem> results = items.Where(item => item.Item1 == 12 &&
                                             item.Item2 != null &&
                                             item.Item2.SubItem == 65 &&
                                             item.Item3.Equals(anotherThingy))
                              .ToList();
List results=items.Where(item=>item.Item1==12&&
item.Item2!=null&&
item.Item2.SubItem==65&&
第3项等于(另一项)
.ToList();
争论的顺序不重要吗?例如,我认为首先执行.Equals会导致整体查询速度变慢,因为Item1==12整数计算是一个更快的操作

如果秩序真的重要,那么它有多重要?当然,调用.Equals之类的方法可能会比比较几个整数慢得多,但与“slow”LINQ的运行方式相比,这是一个相对较小的性能损失吗?当LINQ进行大量的方法调用时,类似.Equals的东西真的会起作用吗?除非它被重写,否则它将执行本机框架代码,对吗?另一方面,标准的MSIL方法调用是否会明显变慢

另外,在这个查询中是否有其他编译器优化可能会加快速度

谢谢你的想法和澄清!
Brett

对于不同的LINQ提供商,答案会有所不同。特别是,LINQ到对象和LINQ到实体的情况非常不同

在LINQ to Objects中,Where运算符将过滤器作为Func接受。Func是一个委托,因此在本讨论中,您可以将其视为函数指针。在LINQ to对象中,您的查询相当于:

static void Main() {
    List<TestItem> results = items.Where(MyFilter).ToList(); 

static boolean MyFilter(TestItem item) {
    return item.Item1 == 12 && 
        item.Item2 != null && 
        item.Item2.SubItem == 65 && 
        item.Item3.Equals(anotherThingy)
}
static void Main(){
列表结果=items.Where(MyFilter.ToList();
静态布尔MyFilter(测试项){
return item.Item1==12&&
item.Item2!=null&&
item.Item2.SubItem==65&&
第3项等于(另一项)
}
需要注意的主要问题是MyFilter是一个普通的C#方法,因此应用普通的C#规则,包括&&的短路行为。因此,条件将按照您编写它们的顺序进行计算。LINQ to对象可以在不同的输入元素上调用MyFilter,但它无法更改MyFilter的功能

在LINQ to Entities和LINQ to SQL中,Where运算符接受作为表达式的筛选器。现在,筛选器作为描述表达式的数据结构传递到Where运算符。在这种情况下,LINQ提供程序将查看数据结构(“表达式树”)LINQ提供者决定如何解释它


在LINQ to Entities和LINQ to SQL的情况下,表达式树将被转换为SQL。然后由数据库服务器决定如何执行查询。服务器肯定可以对条件进行重新排序,并且可能会进行更大的优化。例如,如果SQL表中的某一列包含索引,则如果在条件中引用了,服务器可以选择使用索引,甚至避免查看与特定条件部分不匹配的行。

我考虑的是LINQ to Objects,但我认为这个问题对于LINQ to SQL更为重要。虽然我不知道LINQ,但如果它像其他短路语言一样,顺序很重要,b因为如果要计算的表达式变为绝对真或绝对假,则可以安全地丢弃其余谓词。例如,在表达式
(1==1 | | x==3)中
x==3
永远不会被计算,因为无论结果如何,表达式都是真的。类似的简单示例可能是
(1==0&&x==3)
,其中在
1==0
被发现为false之后,它就退出了,因为表达式不可能是真的。如果这不是您要找的,很抱歉!这就是我所想的,@prelic!但我也在想可能正在进行的任何编译器优化,或者包括方法调用的查询可能是Optimized?@Brett这只是一个纯粹的猜测,但我假设没有DB查询优化,因为如果其他人从外部连接到DB并更改DB,会发生什么?我猜,即使以前执行过,每个查询都会再次执行以维护事务保证,而自包含的应用程序可能能够做更多的假设,但就像我说的,这纯粹是猜测,没有事实依据。查询本身可以优化为更好的形式(更快的)查询,但我怀疑幕后是否有任何缓存或备忘录。谢谢你的详细回答!