C# LINQ对象是否在内部进行任何调优?
我想知道LINQtoObjects如何确定集合中查询的最佳方式 我的意思是,以下LINQ查询之间是否存在任何差异(在LINQ内部的工作方式上):C# LINQ对象是否在内部进行任何调优?,c#,linq-to-objects,C#,Linq To Objects,我想知道LINQtoObjects如何确定集合中查询的最佳方式 我的意思是,以下LINQ查询之间是否存在任何差异(在LINQ内部的工作方式上): var lst1 = ListOfComplexClass.Where(p => p.StrValue == "Whatever") .Select(p => p.StrValue); 及 例如,第一个函数是否会过滤ListOfComplexClass的集合,然后获取StrValu
var lst1 = ListOfComplexClass.Where(p => p.StrValue == "Whatever")
.Select(p => p.StrValue);
及
例如,第一个函数是否会过滤ListOfComplexClass
的集合,然后获取StrValue
属性?
或者它会进行一些调整并首先执行
选择,然后过滤返回的集合吗?在这种特殊情况下,这并不重要。您直接投影一个字符串,因此不会创建新对象,并且仍然只有一个比较。另一方面,在某些情况下(投射到另一种类型中),这可能很重要。我不相信LINQ会试图优化这些预测,因为它们可能包含副作用
我想知道LINQtoObject是否在集合中寻找查询的最佳方式
不,不可能。这里没有“引擎”。这些调用在一个直接链中对彼此的输出起作用。如果第二个比这更快,则必须进行优化
也许LINQtoSQL或LINQtoEntities(IQueryable)可以优化某些东西,但不能优化LINQtoObject Linq to对象不使用像Linq to sql这样的表达式,因此没有这样的优化空间-每个Linq命令都返回另一个可枚举或值。使用中的时可能会有一些优化。。在里面哪里选择..
syntaxebycompiler,但我也不希望出现任何复杂的情况。在您的示例中,首先使用where
应该稍微快一点(至少在理论上),因为where
和select
之间的转换已经被过滤,但我认为我们甚至无法测量这种差异,因为它实际上只是在调用方和被调用方之间传递值。然而,若您要以某种方式转换所选择的值,那个么差异将是明显的,因为您将在已经过滤的集合上创建新对象
例如。。第一个会过滤ListOfComplexClass的集合,然后获取StrValue属性吗?或者它会做一些调整,首先执行Select,然后过滤返回的集合
(我假设您在第一个选项的中选择,是指p=>p.StrValue
。)
事实上,这比那更微妙
假设你在第一个上使用了一个枚举器
var lst1 = ListOfComplexClass.Where(p => p.StrValue == "Whatever")
.Select(p => p.StrValue);
var e = lst1.GetEnumerator();
当您调用e.MoveNext()
时,将发生的情况是Select
将在ListOfComplexClass的迭代器上调用MoveNext()
,其中(p=>p.StrValue==“Whatever”)
将调用MoveNext()
ListOfComplexClass的迭代器,直到它找到一个元素p
,其中p.StrValue==“Whatever”
。然后,此p
的预测结果将作为e.Current
返回
现在让我们考虑第二个问题。让我们假设你对它进行了一次计数
var lst2 = ListOfComplexClass.Select(p => p.StrValue)
.Where(p => p == "Whatever");
var e = lst2.GetEnumerator();
当您调用e.MoveNext()
时,Where
将在ListOfComplexClass的迭代器上调用MoveNext()
。选择(p=>p.StrValue)
,直到它找到一个元素p
,其中p==“which”
。当然,在ListOfComplexClass.Select(p=>p.StrValue)
的迭代器上调用MoveNext()
将在ListOfComplexClass
的迭代器上调用MoveNext()
,并返回该迭代器当前的投影
乔恩·斯基特有一个很好的类比,我在这里将其引用。想象一副随机排列的牌。想象一下这些疑问
var suits = deck.Where(c => c.Suit == Suit.Diamond || c.Suit == Suit.Heart)
.Select(c => c.Suit)
及
现在想象一下使用第一个查询的结果。事情是这样的
选择
询问卡的位置
其中
询问卡片组
*其中
检查卡套
如果卡片的套装是钻石或心脏,它会将卡片返回到Select
,然后Select
将卡片投影到其套装并返回
如果这张牌的花色不是钻石或心形,Where
要求从牌组中取出另一张牌并循环回*
第二个查询是这样的
其中
询问选择
一套西装
选择
询问卡片组
deck
返回要选择的卡
选择
将卡投影到适合的位置
*其中
从选择
检查西装
如果西装是钻石或心脏,其中
返回西装
如果西装不是钻石或心脏,其中
要求选择
另一件西装,并循环回*,如果您呈现的没有区别
但如果你把收费表放在那里的某个地方,它可能会有所不同
LINQtoObject,就像LINQtoSQL一样,仍然使用延迟执行,即使它只是处理内存中的对象
这是因为IEnumerable上的LINQ扩展使用表达式树。这意味着您只能在需要时执行LINQ表达式
通常,如果您链接IEnumerable扩展,那么这不会有什么区别。但是,如果您需要中途更改类型,或者调用类似于ToList的命令,那么这将改变执行顺序。谢谢,当我使用循环收集或将其作为列表返回时,我当然在讨论调优。
var suits = deck.Where(c => c.Suit == Suit.Diamond || c.Suit == Suit.Heart)
.Select(c => c.Suit)
var suits = deck.Select(c => c.Suit)
.Where(c => c == Suit.Diamond || c == Suit.Heart);