我正在研究IQueryable的實現;但是,在我深入研究之前,我想確保我完全理解我需要評估的表達樹會是什麼樣子。特別是,我對LINQ查詢語法在編譯過程中如何轉換爲方法語法感到好奇。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)如何處理與生成的代碼的命名衝突?