2014-09-22 23 views
0

相同值I要綁定的一組回調函數來GUI在C#元素,每個調用用不同的參數相同的處理功能。事件處理總是調用與foreach循環

拼寫出的方式

# Assign element #1 to widget 

widget.Click +=() => {ProcessClick(1) ;} ; 

# Assign element #2 to widget 

widget.Click +=() => {ProcessClick(2) ;} ; 

... 

似乎是多餘的。然而,

Widget widget ; 

foreach (int i in new List<int>() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) 
{ 
    # Assign element i to widget 

    widget.Click +=() => {ProcessClick(i) ;} ; 
} 

一個天真的循環將無法工作,因爲循環將已經過期的任何一次回調被調用,導致ProcessClick(9)爲每個插件的調用。

我覺得應該有一個簡單的解決方案,但我卡住了。

如何將回調函數綁定到GUI元素,每個GUI元素都使用不同的參數調用函數,而不將它們全部拼寫出來?

+1

很多來自Eric Lippert的關於此主題的有用內容http://blogs.msdn.com/b/ericlippert/archive/tags/closures/ – DavidG 2014-09-22 12:24:36

回答

5

i在循環過程中被您的委託人捕獲。你需要它的值複製到一個局部變量在你的循環,使其工作:在變量捕獲

Widget widget ; 

foreach (int i in new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }) 
{ 
    # Assign element i to widget 

    int index = i; 
    widget.Click +=() => {ProcessClick(index) ;} ; 
} 

更多信息,可以發現hereEric Lipper's blog。在後者中,您還可以找到有關C#團隊在C#5中對變量進行邏輯上的循環更改(如DavidG所述)的重大更改的信息。

+3

值得注意的是,這在C#版本5中發生了變化,現在關閉將關閉每次變量的新副本。 – DavidG 2014-09-22 12:35:51

+0

事實上,我逃過的一件事就是'int index'創建了一個* index *實例,它可以被每個lambda函數分別引用。謝謝! – fbmd 2014-09-22 16:05:40

+0

@fbmd DavidG寫道,C#5中的循環變量在循環塊內部,不再像Eric Lippert在這裏所解釋的那樣捕獲:http://ericlippert.com/2009/11/16/closing-over-the -loop-可變認爲對人體有害的部分二/ – 2014-09-22 16:10:18