3 回答

TA貢獻1804條經驗 獲得超8個贊
Lambda表達式就像匿名方法一樣,實際上是非常復雜的野獸。即使我們排除Expression
(.NET 3.5),仍然留下了很多復雜性,尤其是捕獲的變量,這些變量從根本上重新構造了使用它們的代碼(您認為變量成為編譯器生成的類中的字段) ,有一點煙霧和鏡子。
因此,您可以無所事事地使用它們,我一點也不感到驚訝-有很多支持這種魔術的編譯器工作(以及幕后的類型生成)。

TA貢獻1815條經驗 獲得超10個贊
不,您不能在watch / locals /即時窗口中使用lambda表達式。正如Marc所指出的那樣,這非常復雜。不過,我想進一步探討這個話題。
大多數人在調試器中執行匿名函數時不會考慮的是,它不會在真空中發生。定義和運行匿名函數的行為改變了代碼庫的基礎結構。通常,尤其是從即時窗口更改代碼是一項非常困難的任務。
考慮以下代碼。
void Example() {
var v1 = 42;
var v2 = 56;
Func<int> func1 = () => v1;
System.Diagnostics.Debugger.Break();
var v3 = v1 + v2;
}
此特定代碼創建一個單個閉包以捕獲值v1。每當匿名函數使用在其作用域之外聲明的變量時,都需要捕獲閉包。出于所有意圖和目的,此功能中不再存在v1。最后一行實際上更像以下內容
var v3 = closure1.v1 + v2;
如果在調試器中運行示例函數,它將在中斷行處停止?,F在,假設用戶是否在監視窗口中輸入了以下內容
(Func<int>)(() => v2);
為了正確執行此操作,調試器(或更合適的EE)將需要為變量v2創建一個閉包。這很難但并非不可能。
對于EE而言,真正使這項工作變得艱難的是最后一行。現在應該如何執行該行?出于所有目的和目的,匿名函數刪除了v2變量,并將其替換為closure2.v2。所以現在實際上需要閱讀最后一行代碼
var v3 = closure1.v1 + closure2.v2;
然而,要在代碼中實際獲得這種效果,則EE必須更改最后一行代碼,這實際上是ENC動作。盡管可以使用此特定示例,但大部分情況都不可行。
更糟糕的是執行lambda表達式不應創建新的閉包。它實際上應該將數據附加到原始閉包中。此時,您會直接遇到ENC的限制。
不幸的是,我的小例子只能解決我們遇到的問題。我一直說我會寫一篇完整的博客文章,希望這個周末有時間。
- 3 回答
- 0 關注
- 1058 瀏覽
添加回答
舉報