2013-10-06 42 views
0

我想我明白在C#和.NET中如何實現閉包。當CLR檢測到一個函數將被傳遞到它的作用域之外並作用於一個自由變量時,它會將函數和變量打包到一個自定義類中。當一個對象調用它自己的函數之一時,是否將對象作爲第一個變量傳遞給方法的閉包的情況?

那麼這與object稱之爲自己的功能之一時會發生什麼不同呢? object本身作爲第一個變量傳遞給函數,以便如果函數需要該對象的任何其他函數,屬性或字段,則它可以訪問它們。

我想我在這裏錯過了一些東西,想要解釋一下在這兩種情況下會發生什麼:閉合,以及對象正在調用它自己的方法之一的情況。

回答

1

對象的普通方法調用與閉包無關;如果您將該方法調用作爲委託進行打包,您只需要關閉!

爲了理解發生了什麼,您需要對「值類型」和「參考類型」的概念有一個很好的把握。淺談Object在.net中不夠明確,因爲Object位於層次結構的底部,包括值類型(int也是Object)。開始思考純引用類型(如類實例)的方法調用要容易得多。

把你的普通類變量和實例:

List x; // variable declaration 
x = new List(); // instantiation 

,或者在一行:

List x = new List(); 

的您的實例的「身體」會留在這就是所謂的堆內存區域。您正在使用的x僅保留對該內存區域的引用,這就是爲什麼這稱爲reference type

當您使用x變量調用List上的方法時,該方法需要知道要在哪個列表中工作。因此,該方法簡單地獲取對該實例主體的引用,作爲第一個參數this參數。說CLR或編譯器傳遞「對象」是不正確的,因爲對象總是在堆上,它只傳遞一個引用(或一個指針)。

當該方法需要調用同一對象的不同方法時,它只是傳遞與第一個參數(它自己接收的第一個參數)相同的this

一個正常的方法調用是這樣的:

x.Add(Something); // calls instance method "Add" on "x" 

當編譯器看到它知道使用x作爲this呼叫到Add參考(第一個參數,隱藏的一個)。那裏沒有「關閉」!

這裏是一個封閉會是什麼樣子:

List<int> A = new List<int>(); 
List<int> B = new List<int>(); 

Action<int> aDelegate; // <-- declare a delegate type variable 
         // Action<int> is a delegate that returns void and 
         // takes a single int parameter. 

aDelegate = A.Add; // <-- initialize the delegate using an instance method of object A 
aDelegate(7); // <- notice the call! No reference to "A" because "A" is already stored in aDelegate 

aDelegate = B.Add; 
aDelegate(8); // <- notice the call! No reference to "B" because "B" is already stored in aDelegate 

如果您密切關注,當你調用委託(aDelegate(7)),編譯器在某種程度上需要調用Add方法上的對象A會發生什麼樣子,但你看不到,它是隱藏的。代理封裝了對象A的引用和Add方法的地址,這就是爲什麼它被稱爲closure的原因。對比一下當你做aDelegate(8)時會發生什麼;在對象B上調用此時間方法Add,但無法猜測,因爲對象B的引用再次被隱藏在委託(閉包)中。

+0

我可以兩次投票嗎?快速提問:你說的地方「注意通話!對」A「的引用是隱藏的」......它隱藏了嗎?或者'Delegate''aDelegate'已經有'A'的引用,所以'''A「'不需要傳遞給'aDelegate'的調用?由於''A''已經存儲在'aDelegate'中,所以當在'aDelegate'上調用Invoke並且又調用'Add'時,它只是將'A'的引用作爲第一個參數傳遞給'Add'。 – richard

+0

哎呀,還沒有讀完整個東西......我看到我基本上說過你已經解釋過的同樣的東西。 :-) – richard

+0

那麼你能向我解釋封閉和公開的代表嗎?或者我應該爲此打開一個新的QA? – richard

相關問題