匿名方法定義
匿名方法的聲明
匿名方法的使用
範圍捕獲局部變量或執行個體狀态
匿名函數會捕獲變量,并延長對象的生命周期
結束匿名方法捕獲局部變量-靜态匿名函數
匿名方法是沒有名稱隻有主體的方法。 在匿名方法中您不需要指定傳回類型,它是從方法主體内的 return 語句推斷的。 匿名方法是通過使用 delegate 關鍵字建立委托執行個體來聲明的。
第一種方式:<code></code>
第二種方式:可以将建立的匿名方法轉換為具有任何參數清單的委托類型。這是 lambda 表達式不支援的匿名方法的唯一功能。 在所有其他情況下,lambda 表達式是編寫内聯代碼的首選方法。
從 C# 9.0 開始,可以使用棄元指定該方法不使用的兩個或更多個匿名方法輸入參數:
<code></code>為實作向後相容性,如果隻有一個參數名為 <code>_</code>,則将 <code>_</code> 視為匿名方法中該參數的名稱。
從 C# 9.0 開始,可以在匿名方法的聲明中使用 <code>static</code> 修飾符:
靜态匿名方法無法從封閉範圍捕獲局部變量或執行個體狀态。
總結:
匿名函數會捕獲目前上下文的局部變量,捕獲是引用位址不是指派,延長對象的生命周期; 捕獲的變量将不會被作為垃圾回收,直到此委托或表達式樹被回收掉。
這邊說的目前上下文就是private public interal protected聲明的那些指函數、變量等多作用域範圍
也就是說,隻要某個方法中存在沒有被回收的匿名函數/lambda 表達式/表達式樹,那麼目前上下文的對象直到這些匿名函數被回收之前都不會被回收,即便已經設為了 null。
案例:
測試代碼是這樣的:
需要驗證的是 <code>MainPage</code> 對象是否被回收。然而在這段代碼中,<code>MainPage</code> 并沒有被回收;然而去掉最後一行,<code>MainPage</code> 便可以正常回收。關鍵是,即便是在 Console.WriteLine 上打下斷點,讓代碼永遠不會執行到最後一句,也不會改變回收的結果。
由于 <code>DoSomething</code> 中的委托參數恰好就是 <code>MainPage</code> 類型的,不禁讓人覺得可能是此函數做了一些奇怪的事情。然而畢竟參數中傳入的委托參數隻是形參,理論上不應該影響到外部對象的回收。那麼影響的隻可能是變量的捕獲了。
于是,我們将最後一行換成别的函數别的參數:
或者将整個這一句提取成新的函數:
那麼,回收就會正常進行。
現在,不執行這個受争議的函數了,我們使用空的匿名函數。
一樣會導緻不回收。
在微軟官方的《C# 規範 5.0》(點此下載下傳)的第 7.15.5.1 章節中有說到:
When an outer variable is referenced by an anonymous function, the outer variable is said to have been captured by the anonymous function. Ordinarily, the lifetime of a local variable is limited to execution of the block or statement with which it is associated (§5.1.7). However, the lifetime of a captured outer variable is extended at least until the delegate or expression tree created from the anonymous function becomes eligible for garbage collection.

匿名函數會捕獲目前上下文的局部變量,延長對象的生命周期;直到此委托或表達式樹被回收掉。
您可以在lambda或匿名方法上利用static修飾符,以確定您不會無意中從封閉的上下文中捕獲本地或執行個體狀态。這對于提高應用程式的性能非常友好。
程式設計是個人愛好