2010-04-13 65 views
3

我想遍歷所有組件,併爲那些誰實現ISupportsOpen允許打開一個項目。 問題是,當匿名方法被調用,則組件變量始終是相同的元素(從外部範圍來自IEnumerable)C#匿名方法變量範圍問題與IEnumerable <T>

foreach (ISupportsOpen component in something.Site.Container.Components.OfType<ISupportsOpen>()) 
{ 
    MyClass m = new MyClass(); 
    m.Called += new EventHandler(delegate(object sender, EventArgs e) 
    {       
     if (component.CanOpenProject(..)) component.OpenProject(..); 
    }); 

    itemsList.Add(m); 
} 

究竟應該如何解決,好嗎?

回答

5

只是不要close over the loop variable - 複製:

foreach (ISupportsOpen component in 
     something.Site.Container.Components.OfType<ISupportsOpen>()) 
{ 
    ISupportsOpen copy = component; 
    MyClass m = new MyClass(); 
    m.Called += new EventHandler(delegate(object sender, EventArgs e) 
    {       
     if (copy.CanOpenProject(..)) copy.OpenProject(..); 
    }); 

    itemsList.Add(m); 
} 

你得到copy變量的新「實例」爲每個循環迭代這樣 - 所以每個代表能捕捉到不同的實例。之前,每個代表都在捕獲同一個變量。

(這在某種程度上是一個重複的問題,但它是一種問題,就是比較難以尋找的,所以我很高興回答了很多次。)

+0

我只是好奇,爲什麼當知道實例正在被使用時,運行時不會將該實例保存在內存中?爲什麼代表在捕獲相同的變量之前? – 2010-04-13 09:52:12

+0

@ PaN1C_Showt1Me:語言規範根據單個變量定義'foreach';該變量被捕獲,所以它都按照規範工作。 (這是一種語言,而不是運行時間的事情。)有關更多詳細信息,請參閱Eric的博客文章(鏈接)。我敢肯定,如果語言設計師有時間機器,他們會改變foreach的行爲 - 但現在已經太晚了。 – 2010-04-13 09:59:14