C# - Modifier la valeur d'un dictionnaire de paires clé-valeur, tandis que dans le foreach
J'ai ce code qui est exécuté à chaque image d'un jeu:
foreach (var repeaterAction in conditionTimes.Keys)
{
if (repeaterAction.Condition() == true)
{
if (conditionTimes[repeaterAction] == TimeSpan.Zero)
{
repeaterAction.Action();
}
else if (conditionTimes[repeaterAction] >= repeaterAction.InitialLapse)
{
repeaterAction.Action();
conditionTimes[repeaterAction] -= repeaterAction.ActionInterval;
}
conditionTimes[repeaterAction] += gameTime.ElapsedGameTime;
}
else
{
conditionTimes[repeaterAction] = TimeSpan.Zero;
}
}
Ce qui me donne l'erreur suivante:
Collection a été modifiée; opération d'énumération peut pas s'exécuter.
Est-il un moyen de modifier la valeur de la paire clé-valeur à l'intérieur de la boucle foreach, sans copier le Dictionnaire à chaque frame?
OriginalL'auteur James | 2011-02-23
Vous devez vous connecter pour publier un commentaire.
Je le Conseille de ne pas essayer de modifier une collection tout en parcourant avec les dictionnaires toutefois, il est possible puisque les clés d'accès est disponible. Juste ajouter
.ToArray()
après laconditionTimes.Keys
dans leforeach
puis sur les touches devient une collecte séparée et vous pouvez modifier le dictionnaire:Vous devez également modifier vous êtes le code de sorte que si les principaux changements que vous avez fait supprimer une entrée du dictionnaire et de l'ajout de la nouvelle, parce que les touches ne peut pas être changé, juste enlevé.
De nouveau ce n'est pas recommandé.
OriginalL'auteur ntziolis
Non, vous ne pouvez pas. Il y a une méchant option que vous pourriez utiliser:
Ensuite, vous devez créer (dire) un
Dictionary<string, WrappedValue<int>>
... itérer sur les paires clé/valeur, et de modifier la valeur dans l'emballage plutôt que de faire de l'entrée de référence à un autre wrapper.Je ne pense pas que je recommanderais ce bien serait - il difficile à utiliser, et facile à abus.
Une autre option, si vous êtes en utilisant .NET 4 est d'utiliser
ConcurrentDictionary
, qui ne permettre les modifications concurrentes.OriginalL'auteur Jon Skeet
Désolé, vous ne pouvez pas.
Je suppose que votre meilleur pari est de créer un nouveau Dictionnaire, puis il échange avec l'ancien lorsque vous en avez terminé avec le
foreach
boucle.OriginalL'auteur Simone
vous devez utiliser un autre motif pour faire ce que vous essayez de le faire parce que pour chaque ne vous permet pas de changer l'agent recenseur vous êtes en boucle. Imaginez si vous exécutez un foreach sur une liste triée depuis le début, vous commencez le traitement d'élément avec la clé="Un", puis vous allez à "B", puis vous changez de "C" à "B", ce qui va arriver? Votre liste est recouru et vous ne savez plus ce que vous êtes en boucle et où vous êtes.
en général, vous "pourrait" le faire avec un for(int i=dictionnaire.count-1; i>=0; --i) ou quelque chose comme cela, mais cela dépend aussi de votre contexte, je voudrais vraiment essayer d'utiliser une autre approche.
OriginalL'auteur Davide Piras
Une approche commune est de se rappeler les touches que vous souhaitez modifier dans la première boucle, puis une seconde qui passe en boucle sur les rappeler clés et les changements du dictionnaire original. Qui évite de créer un tout nouveau dictionnaire avec tous les éléments.
OriginalL'auteur TheEye
Vous ne pouvez pas modifier une collection lors de l'énumération à l'intérieur d'un
foreach
déclaration. Donc, vous devez le copier à chaque fois (il suffit de copier les Clés). Une autre option serait de stocker une clé séparée de la liste à tout moment (par exemple, en encapsulant le dictionnaire à l'intérieur d'une classe qui gère ce). quelque chose comme:Bien sûr, dans un tel environnement, vous devez assurez-vous que le dictionnaire et la liste sont synchronisés...
OriginalL'auteur Ohad Schneider