2009-02-24 21 views
11

因此,每次我在一個方法內寫入lambda表達式或匿名方法時,我都沒有得到的相當,我不得不重新編譯並重新啓動整個應用程序或單元測試框架,以便修復它。這非常惱人,而且最終浪費的時間比通過首先使用這些構造所節省的時間要多。儘管Linq和lambdas是我最喜歡的C#特性之一,但如果可以的話,我儘量遠離它們,這太糟糕了。爲什麼我不能在調試器中編輯一個包含匿名方法的方法?

我想這是爲什麼它有一個很好的技術理由,也許有人知道?此外,有沒有人知道它是否會在VS2010中修復?

謝謝。

回答

14

是的,有一個很好的理由爲什麼你不能這樣做。簡單的原因是成本。在C#(或VB)中啓用此功能的成本很高,爲極其

編輯一個lambda函數是一類ENC問題的一個特例,當前的ENC(Edit'n'Continue)體系結構很難解決這個問題。即,這是非常困難的ENC,其在ENC將執行以下操作中的一個的任何方法: -

  1. 生成的元數據中的一類
  2. 編輯的形式,或者生成一個通用的方法

的第一個問題更多的是邏輯約束,但它在ENC體系結構中也遇到了一些限制。也就是說,問題在於產生頭等並不是非常困難。有什麼麻煩的是在第二次編輯後生成這個類。 ENC引擎不僅需要跟蹤符號表,而且還需要跟蹤生成的代碼。通常情況下,這並不是那麼糟糕,但是當生成的類的形狀基於使用它的上下文(因爲使用閉包的lambdas時),這變得越來越困難。更重要的是,你如何解決這個過程中已經存在的類的實例的差異?

第二個問題是CLR ENC架構的嚴格限制。 C#(或VB)無法解決這個問題。

Lambdas不幸遇到了這兩個問題。簡短的說法是,對一個lambda進行ENC化,會在現有類中引入大量突變(這可能是也可能不是由其他ENC產生的)。解決新代碼與當前進程空間中現有的閉包實例之間的差異是一個大問題。而且,lambda比其他代碼更傾向於使用泛型,並且碰到問題#2。

細節非常多毛,並且對於普通的SO回答有點過分。我曾考慮寫一篇關於這個主題的冗長博客文章。如果我解決它,我會把它鏈接回這個特定的答案。

0

重新啓動單元測試應該需要幾秒鐘的時間。我從來不喜歡「編輯和繼續」的模式,說實話 - 你應該總是從頭開始重新運行IMO,以防萬一執行中途改變會影響早期運行的代碼。鑑於此,你最好使用可以非常快速地運行的單元測試。如果你的單元測試需要一段難以忍受的時間才能開始,那麼你應該考慮解決這個問題。

編輯:至於爲什麼它不工作 - 你可能會發現它適用於一些lambda,但不適用於其他人。不捕獲任何變量的Lambda表達式(包括this)被緩存在一個私有靜態變量中,以便只創建一個委託實例。更改代碼意味着重新初始化可能會產生我懷疑有趣的副作用的變量。

+0

我同意....但它不是問題的答案。 – 2009-02-24 14:54:15

+0

我知道你會知道答案;-) – 2009-02-24 14:56:26

+0

海事組織對許多問題的答案是避免陷入痛苦的境地開始。 – 2009-02-24 15:00:21

1

根據Supported Code Changes的列表,您不能將字段添加到現有類型。匿名方法被編譯成奇怪的類(kinda <>_c__DisplayClass1),這正是:類型。即使您對匿名方法的修改可能不包括更改封閉變量集(添加那些會改變現有類的字段),但我想這就是無法修改匿名方法的原因。

1

這是一個有點可惜,此功能在VB部分支持,但不是在C#: http://msdn.microsoft.com/en-us/library/bb385795.aspx

實現在C#中同樣的行爲就會減少80%的疼痛級別包含lambda表達式的功能,我們不需要修改lambda表達式或任何依賴它們的表達式,也可能不需要「怪物成本」。

相關問題