【发布时间】:2017-09-15 14:58:13
【问题描述】:
我正在研究 IQueryable 的实现;但是,在我深入研究之前,我想确保我完全理解我需要评估的表达式树会是什么样子。特别好奇LINQ查询语法在编译过程中是如何转换成方法语法的。
我正在使用 LINQPad 查看编译器生成的方法。我注意到在嵌套迭代中会生成一个临时变量名称来存储上层迭代的状态。这是一个例子:
from Event in EventQueue
from Ack in Event.Acknowledgements
where Ack.User == User.Name
select Event
这相当于:
EventQueue
.SelectMany(
Event => Event.Acknowledgements,
(Event, Ack) =>
new
{
Event = Event,
Ack = Ack
}
)
.Where(temp0 => (temp0.Ack.User == User.Name))
.Select(temp0 => temp0.Event)
当然,我的第一反应是尝试打破它,看看会发生什么。所以我写了以下查询:
from Event in EventQueue
from Ack in Event.Acknowledgements
let temp0 = Ack.User
where Ack.User == temp0
select Event
这几乎是一个“WHERE 1 = 1”并返回所有事件;但是,我不明白它是如何工作的,因为我得到的方法链永远不会编译:
EventQueue
.SelectMany(
Event => Event.Acknowledgements,
(Event, Ack) =>
new
{
Event = Event,
Ack = Ack
}
)
.Select(
temp0 =>
new
{
temp0 = temp0,
temp0 = temp0.Ack.User // Anonymous object with identically-named properties
}
)
.Where(temp1 => (temp1.temp0.Ack.User == temp1.temp0))
.Select(temp1 => temp1.temp0.Event)
这使我得出结论,LINQPad 没有从编译器中提取这些方法链,因为查询有效,而此方法链显然不能。 LINQPad 很可能会自行生成方法链。
C# 编译器(在本例中为 Roslyn)如何处理与生成代码的命名冲突?
【问题讨论】: