gpt4 book ai didi

c# - 了解 C# 编译器如何处理链接 linq 方法

转载 作者:太空狗 更新时间:2023-10-29 21:19:56 25 4
gpt4 key购买 nike

当我链接 linq 方法时,特别是多次链接相同的方法时,我正在努力思考 C# 编译器会做什么。

简单示例:假设我正在尝试根据两个条件过滤一系列整数。

最明显的做法是这样的:

IEnumerable<int> Method1(IEnumerable<int> input)
{
return input.Where(i => i % 3 == 0 && i % 5 == 0);
}

但我们可以也链接 where 方法,每个方法有一个条件:

IEnumerable<int> Method2(IEnumerable<int> input)
{
return input.Where(i => i % 3 == 0).Where(i => i % 5 == 0);
}

我看过 Reflector 中的 IL;这两种方法显然不同,但目前进一步分析超出了我的知识:)

我想知道:
a)编译器在每个实例中的不同之处,以及原因。 b) 是否有任何性能影响(不是试图进行微优化;只是好奇!)

最佳答案

(a) 的答案很简短,但我将在下面详细介绍:

编译器实际上并不进行链接——它发生在运行时,通过对象的正常组织!这里的魔法远没有乍一看那么神奇 - Jon Skeet recently completed the "Where clause" step在他的博客系列 Re-implementing LINQ to Objects 中。我建议通读一遍。

简而言之,发生的事情是这样的:每次调用 Where 扩展方法时,它都会返回一个新的 WhereEnumerable 对象,该对象有两个东西 - 对前面的 IEnumerable(您在 Where 上调用的那个),以及您提供的 lambda。

当您开始遍历此 WhereEnumerable 时(例如,在您代码后面的 foreach 中),在内部它只是开始遍历 IEnumerable 已引用。

"This foreach just asked me for the next element in my sequence, so I'm turning around and asking you for the next element in your sequence".

这一直沿着链向下直到我们到达原点,它实际上是某种数组或真实元素的存储。当每个 Enumerable 然后说“好的,这是我的元素”时,将它传回到链中,它也应用自己的自定义逻辑。对于 Where,它应用 lambda 来查看元素是否符合条件。如果是这样,它允许它继续到下一个调用者。如果失败,它将在该点停止,返回到其引用的 Enumerable,并请求下一个元素。

这种情况一直发生,直到每个人的 MoveNext 返回 false,这意味着枚举完成,不再有元素。

要回答 (b)总是 有区别,但在这里它太微不足道了。别担心:)

关于c# - 了解 C# 编译器如何处理链接 linq 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4160981/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com