public virtual void OnRegistrationJoin(RegistrationJoinEventArgs e) { foreach (Mobile member in e.Team) { member.SendMessage(1161, "You join the {0}.", EventFullName); if (e.Team.Count > 1) { Joinees.Remove(member); member.SendMessage(1161, "Your team formation is:"); int i = 0; foreach (Mobile parter in e.Team.Where(partner => partner != member).ToList()) { member.SendMessage(1150, "{0}: {1}.", ++i, partner.Name); } } } Members.Add(e.Team); } I get "access to modified closure" warning by resharper, I was wondering what's so wrong with this code, since all I do in the inner loop is send a message?
3 Réponses :
Je suppose qui modifie une variable fermée utilisée dans la Lambda P> membre.SENDMessage code> pourrait modifier
membre code> p>
Pas vraiment. Le problème est la boucle de foresach externe qui modifie la variable code> de la variable code> dans la Lambda.
Le problème est dans: la variable La raison en est un problème est que c # génère une méthode pour ensuite transmettre comme délégué à < code> où code>. Cette méthode a besoin d'un accès direct à puis c # peut "capturer" cette valeur dans une construction appelée "fermeture" et transmettez-la au généré méthode. Cela garantira que lorsque membre code> est une référence directe à la variable code> de la variable code> dans la portée extérieure. Pendant que vous n'avez peut-être pas de problème avec ceci dans le code ci-dessus, il est problématique lorsque vous exécutez le code sur plusieurs threads ou si vous n'évaluez pas la Lambda dans le
où code> méthode (pour Exemple, en utilisant
iquéryable code> au lieu de
iEnumerable code>). p>
memeber code>. Si vous deviez attribuer la référence à une autre variable comme celle-ci: p>
membre code> modifie la valeur que vous vous attendez à ce que ce soit lorsque vous le transmettez à
où code> n'est pas modifié. P> P>
+1: En fin de compte, les problèmes les plus importants que je vois pour la plupart des gens sont différés d'exécution.
Facilement corrigé en faisant Var Closuremembernember = membre. Et en utilisant des closeumember dans la linq.
@Femarf - mais c'est l'évolution de la référence qui est le problème, pas l'instance changeante.
Bien sûr que c'est. Mais le comportement de votre Closuremember code> sera exactement la même - chaque itération, elle passera à l'objet actuel. S'il n'utilisait pas la requête directement mais différée, seul le dernier membre de la séquence de Foreach'ed serait utilisé.
Oh, vous vouliez dire avoir attribuer ClosEremember code> en dehors de la Lambda. Bien sûr, cela fonctionnera. Désolé.
Merci pour l'explication, pouvez-vous éditer avec un exemple de cas simple où cela deviendrait un problème?
La pièce Resharper se plaint est Remarque: vous n'avez pas à utiliser e.team.where (partenaire => partenaire! = membre) .tolist () code>, comme le membre référencé code> sera modifié. Dans ce cas, ce n'est pas un problème, mais dans d'autres cas, cela peut être un problème. P>
tolist () code>, qui oblige l'évaluation désireuse du
ienumerable
e.team.where (partenaire => partenaire! = Membre) code>. P>
Dupliqué possible de Accès à la fermeture modifiée et plusieurs autres.