string [] files = new string[2];
files[0] = "ThinkFarAhead.Example.Settings.Configuration_Local.xml";
files[1] = "ThinkFarAhead.Example.Settings.Configuration_Global.xml";
//Resharper complains this is an "access to modified closure"
for (int i = 0; i < files.Length; i++ )
{
// Resharper disable AccessToModifiedClosure
if(Array.Exists(Assembly.GetExecutingAssembly().GetManifestResourceNames(),
delegate(string name) { return name.Equals(files[i]); }))
return Assembly.GetExecutingAssembly().GetManifestResourceStream(files[i]);
// ReSharper restore AccessToModifiedClosure
}
Ce qui précède semble fonctionner correctement, bien que ReSharper se plaint qu'il s'agit d'un "accès à une fermeture modifiée". Quelqu'un peut-il faire la lumière sur cette question?
(ce sujet a continué ici )
Réponses:
Dans ce cas, ce n'est pas grave, car vous exécutez réellement le délégué dans la boucle.
Si vous enregistrez le délégué et l'utilisez plus tard, cependant, vous constaterez que tous les délégués lèveraient des exceptions lorsqu'ils essaient d'accéder aux fichiers [i] - ils capturent la variable
i
plutôt que sa valeur au moment des délégués création.En bref, c'est quelque chose dont vous devez être conscient en tant que piège potentiel , mais dans ce cas, cela ne vous fait pas de mal.
Voir le bas de cette page pour un exemple plus complexe où les résultats sont contre-intuitifs.
la source
Je sais que c'est une vieille question, mais j'ai récemment étudié les fermetures et j'ai pensé qu'un exemple de code pourrait être utile. Dans les coulisses, le compilateur génère une classe qui représente une fermeture lexicale pour votre appel de fonction. Cela ressemble probablement à quelque chose comme:
Comme mentionné ci-dessus, votre fonction fonctionne car les prédicats sont appelés immédiatement après la création. Le compilateur va générer quelque chose comme:
D'un autre côté, si vous deviez stocker puis invoquer plus tard les prédicats, vous verriez que chaque appel unique aux prédicats appellerait vraiment la même méthode sur la même instance de la classe de fermeture et utiliserait donc la même valeur pour je.
la source
"fichiers" est une variable externe capturée car elle a été capturée par la fonction de délégué anonyme. Sa durée de vie est prolongée par la fonction de délégué anonyme.
Variables externes sur MSDN
la source