2010-04-13 3 views
3

J'essaie de parcourir tous les composants et pour ceux qui implémente ISupportsOpen permettre d'ouvrir un projet. Le problème est lorsque la méthode anonyme est appelée, la variable composant est toujours le même élément (comme provenant du champ extérieur de IEnumerable)C# Anonyme problème de portée variable avec 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); 
} 

Comment devrait-il être résolu, s'il vous plaît?

Répondre

5

Il suffit de ne pas close over the loop variable - le copier:

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); 
} 

De cette façon, vous obtenez une nouvelle « instance » de la variable copy pour chaque itération de la boucle - de sorte que chaque délégué capturer cette instance différente. Avant, chaque délégué capturait la même variable.

(Ceci est en quelque sorte une double question, mais il est le genre de problème qui est relativement difficile de rechercher, donc je suis heureux de répondre à plusieurs reprises.)

+0

Je suis juste curieux, pourquoi le run-time ne garde-t-il pas cette instance en mémoire quand il sait que l'instance est utilisée? Pourquoi le délégué a-t-il capturé la même variable? –

+0

@ PaN1C_Showt1Me: La spécification de langage définit 'foreach' en termes d'une seule variable; cette variable est capturée, donc tout fonctionne selon la spécification. (C'est une chose de langue plutôt qu'une chose d'exécution.) Voir l'article de blog d'Eric (lié) pour plus de détails. Je suis sûr que si les concepteurs de langage avaient une machine à remonter le temps, ils changeraient le comportement de foreach - mais il est trop tard maintenant. –

Questions connexes