理解C 中的閉包

2021-08-21 05:24:03 字數 2205 閱讀 1198

內層的函式可以引用包含在它外層的函式的變數,即使外層函式的執行已經終止。但該變數提供的值並非變數建立時的值,

而是在父函式範圍內的最終值。

使用閉包,我們可以輕鬆的訪問外層函式定義的變數,這在匿名方法中普遍使用。比如有如下場景,在winform應用程式中,我們希望做這麼乙個效果,當使用者關閉窗體時,給使用者乙個提示框。我們將新增如下**:

private

void form1_load(object

sender, eventargs e)

;}

若不使用匿名函式,我們就需要使用其他方式來將tipwords變數的值傳遞給formclosing註冊的處理函式,這就增加了不必要的工作量。

應用閉包,我們要注意乙個陷阱。比如有乙個使用者資訊的陣列,我們需要遍歷每乙個使用者,對各個使用者做處理後輸出使用者名稱。

public

class

usermodel

public

intuserage

}

listuserlist = new list,

new usermodel,

new usermodel

};for(int i = 0 ; i < 3; i++));}

我們預期的輸出是, jiejiep, xiaoyi, zhangzetian

但是實際我們執行後發現,程式會報錯,提示索引超出界限。

為什麼沒有達到我們預期的效果呢?讓我們再來看一下閉包的概念。內層函式引用的外層函式的變數的最終值。就是說,當執行緒中執行方法時,方法中的i引數的值,始終是userlist.count。原來如此,那我們該如何

避免閉包陷阱呢?c#中普遍的做法是,將匿名函式引用的變數用乙個臨時變數儲存下來,然後在匿名函式中使用臨時變數。

listuserlist = new list,

new usermodel,

new usermodel

};for(int i = 0 ; i < 3; i++));}

我們再執行來看,輸出依次為 jiejiep,xiaoyi, zhangzetian.注意,每次的輸出順序可能不同。

提出了問題,給出了解決方案,我們總算知道該怎麼正確使用閉包了。但是dotnet是如何實現閉包的呢?執著的程式猿們,不會滿足於這種表象的解決方案,讓我們來看看dotnet是如何實現閉包的。我們可以微軟提供的isdasm.exe來檢視編譯後的**。我們先來看看有問題的**。將il**翻譯後,可以得到如下的偽**。

public

class

tempclass5

public

class

tempclass8

}

public

class

program

); c55.userlist.add(

new usermodel);

c55.userlist.add(

new usermodel);

tempclass8 c8 = new

tempclass8();

c8.c5 =c55;

waitcallback callback =c8.showmessage;

for(int c8.i=0; c8.i < 3; c8.i++)

}

原來,編譯器為我們生成了乙個臨時類,該類包含乙個 int成員i,乙個tempclass5例項c5, 乙個例項方法 showmessage(object) 。再看看遍歷部分的**,我們頓時就豁然開朗了,原來一直都只有乙個 tempclass8例項,遍歷時始終改變的是tempcls物件的i欄位的值。所以最後輸出的,始終是最後乙個遍歷得到的元素的 username 。

我們再來看看使用臨時變數後的**,編譯器是如何處理的呢。

public

class

program

); c55.userlist.add(

new usermodel);

c55.userlist.add(

new usermodel);

for(int i=0; i < 3; i++)

}

我們看到,使用臨時變數這種解決方案時,編譯器相當於是每次遍歷時都例項化了乙個 tempclass8物件。所以內層函式引用的c8的i成員始終是遍歷對應的元素。故能有效的解決閉包帶來的陷阱。

Spark中閉包的理解

概念的理解 函式可以訪問函式外面的變數,但是函式內對變數的修改,在函式外是不可見的。rdd相關操作都需要傳入自定義閉包函式 closure 如果這個函式需要訪問外部變數,那麼需要遵循一定得規則,否則會丟擲執行時異常。閉包函式傳入到節點時,需要經過下面的步驟 注意 外部變數在閉包內的修改不會被反饋到驅...

理解Python中的閉包

理解python中的閉包 1.定義 閉包是函式式程式設計的乙個重要的語法結構,函式式程式設計是一種程式設計正規化 而面向過程程式設計和物件導向程式設計也都是程式設計正規化 在面向過程程式設計中,我們見到過函式 function 在物件導向程式設計中,我們見過物件 object 函式和物件的根本目的是...

JS中閉包的理解

閉包其實就是乙個函式,什麼樣的函式?能夠訪問另乙個函式作用域中變數的函式。在回答這個問題之前,我先提乙個假設,我們都知道在內部的函式可以訪問外部函式的變數,假設現在就是有這麼乙個需要,需要外部環境來訪問函式的內部變數,怎麼辦?這時就要用到閉包,這就要牽扯到閉包的實現原理,即作用域鏈的工作。每當函式建...