C# Lambda 和 匿名函数的GC总结
生活随笔
收集整理的這篇文章主要介紹了
C# Lambda 和 匿名函数的GC总结
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
關于Lambda和 匿名函數,閉包的GC,其實可以總結為兩條。
為了方便理解,以舉例說明,首先我們定義變量,靜態變量,以及函數如下:
static int staticVariable = 0;int variable = 0;private void Func(Action callback){}private void StaticFunc(Action callback){}private void Callback(){}private void Callback2(){variable++;}private static void StaticCallback(){staticVariable++;}總結1:若是一個匿名函數引用到外部變量,則會造成一個閉包,C#為了實現這一點會生成一個匿名類(記住,類都是引用類型)來保存用到的外部變量,因此當調用這個閉包時,首先會實例化一個副本,同時會采用外部變量實際值來初始化這個副本,最終致使會在堆上分配內存。也就是說閉包就一定會產生內存分配
總結2: 在C#中全部方法的引用都是引用類型,都會被分配到堆中。把一個方法做為參數傳遞時,都會產生臨時的內存分配,無論傳遞的是匿名方法還是已經定義的方法。
網上有的文章是這么寫的,但是實際上,紅色這句話應該是錯誤的,當傳遞的是已經定義的方法時,是一定會產生內存分配,當傳遞的是匿名方法時,要看該匿名方法是否是閉包。
例如:
void Update(){//傳遞的是已經定義的方法,有內存分配Func(Callback);//傳遞的是已經定義的方法,雖然是靜態函數,也有內存分配Func(StaticCallback);//傳遞的匿名方法,由于是靜態函數不是閉包,無內存分配Func(() => StaticCallback());//傳遞的匿名方法,由于是靜態變量不是閉包,無內存分配Func(() =>{staticVariable++;});//傳遞的匿名方法,由于是靜態函數不是閉包,無內存分配Func(() =>{StaticCallback();});//傳遞的匿名方法,由于是普通成員函數是閉包,有內存分配Func(() => Callback());//傳遞的匿名方法,不是閉包,無內存分配Func(() =>{int i = 0;i++;});//傳遞的匿名方法,是閉包,有內存分配Func(() =>{variable++;});}更進一步測試:
public Action test;void Update(){//是閉包,有內存分配test = () =>{variable++;};//傳遞的是函數名,有內存分配test = Callback;//傳遞的是函數名,有內存分配test = Callback2;//傳遞的是函數名,有內存分配test = StaticCallback;//傳遞的是匿名函數,不是閉包,無內存分配test = () => { };//傳遞的是匿名函數,不是閉包,無內存分配test = () => { StaticCallback(); };}因此:
1) 盡量避免將方法作為參數傳遞,如果無法避免,優先采用匿名方法,且盡量不要產生閉包,比如可以將所需的外部變量傳入而不是直接應用
2)盡量避免使用閉包,如果無法避免,絕對不能每幀執行的函數中使用閉包
總結
以上是生活随笔為你收集整理的C# Lambda 和 匿名函数的GC总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软媒时间---任务栏滚动工具
- 下一篇: 用linq查询html中div个数,C#