我会尽最大努力去理解它,你让我知道我哪里出错了。
为简单起见,我们假设我们生活在一个只有
的单词中1
,2
,3
,4
,5
%
,>
及其通常的预防性我想忽略当我做的事情
List<int> All = new List<int> { 1, 2, 3, 4, 5 };
IEnumerable<int> Filtered = from i in All
where i % 2 == 1
orderby i descending
select i;
foreach ( var i in Filtererd )
{
Console.WriteLine(i);
}
我首先理解的是查询本身不会创建Ienumerable<int>
;它会创建与Expression Tree关联的查询。查询返回的元素在编译器创建的不可见函数中yield
,如
public static IEnumerable<int> MyInvisibleFunction ( List<int> Source )
{
foreach ( int i in Source.Reverse() )
{
if ( i % 2 == 1 )
{
yield return i;
}
}
}
(当然这是一个奇怪的例子,因为Source.Reverse()
本身就是一个查询,但无论如何......)
现在我很困惑表达发辫在这里发挥作用。当我想到表达树时,我会想到像
这样的树 (3 % 1 > 0)
/ \
/ \
(3 % 1) > 0
/ \
3 % 1
在我创造的小世界里。但是,在我的LINQ查询中,这样的树会在哪里播放
from i in All
where i % 2 == 1
orderby i descending
select i
???这是我不明白的。我正在查看Expression class,我看到它如何创建我展示的示例树,但我不知道它会在我的查询中发挥作用。
答案 0 :(得分:8)
我会尽力帮助你理解它,你让我知道我哪里出错了。
行。
我首先理解的是查询本身不会创建
Ienumerable<int>
;
这句话是完全错误的。
它创建与查询关联的表达式树。
这句话也完全错了。
查询返回的元素在编译器
创建的不可见函数中生成
这句话也完全错了。
这样的树在我的LINQ查询中进行播放
没有。您的查询不使用表达式树。
我正在查看Expression类,我看到它如何创建我展示的示例树,但我看不到它会发挥作用
没有。
想要掩饰我做的事情
List<int> All = new List<int> { 1, 2, 3, 4, 5 };
IEnumerable<int> Filtered = from i in All
where i % 2 == 1
orderby i descending
select i;
foreach ( var i in Filtererd )
Console.WriteLine(i);
让我们分解吧。首先,编译器将其转换为
List<int> All = new List<int> { 1, 2, 3, 4, 5 };
IEnumerable<int> Filtered = All.Where(i => i % 2 == 1).OrderBy(i => i);
foreach ( var i in Filtererd )
Console.WriteLine(i);
接下来编译器执行重载解析并评估扩展方法
List<int> All = new List<int> { 1, 2, 3, 4, 5 };
IEnumerable<int> Filtered =
Enumerable.OrderBy<int>(
Enumerable.Where<int>(All, i => i % 2 == 1)),
i => i));
foreach ( var i in Filtererd )
Console.WriteLine(i);
接下来的羔羊被玷污了:
static bool A1(int i) { return i % 2 == 1; )
static int A2(int i) { return i }
...
List<int> All = new List<int> { 1, 2, 3, 4, 5 };
IEnumerable<int> Filtered =
Enumerable.OrderBy<int>(
Enumerable.Where<int>(All, new Func<int, bool>(A1))),
new Func<int, int>(A2)));
foreach (var i in Filtererd )
Console.WriteLine(i);
实际上,这并不是羔羊如何完全被贬低;它们也被缓存,但让我们忽略这个细节。
我认为你不希望foreach脱毒。有关详细信息,请参阅C#规范。
如果您想知道Where和OrderBy的作用,请阅读源代码。
答案 1 :(得分:1)
表达式树不会在您的查询中发挥作用,因为您的源是常规的内存列表。 - Theodoros Chatzigiannakis
这是真的。
没有生成不可见的迭代器函数。您的查询转换为:
List<int> All = new List<int> { 1, 2, 3, 4, 5 };
IEnumerable<int> Filtered =
All
.Where(i => i % 2 == 0)
.OrderByDescending(i => i);
不需要自定义迭代器。该语言只调用现有的库函数。
IQueryable
的情况相同,只是lambda参数不作为委托传递,而是作为表达式树传递。
您可以通过AsQueryable()
来电here中的评论来查看此操作。