Lorsque vous obtenez une clé d'un dictionnaire dont vous n'êtes pas sûr, vous utilisez généralement TryGetValue
au lieu de ContainsKey
+ l'indexeur get pour éviter la surcharge de vérification de la clé deux fois. En d'autres termes, ceci:
string password;
if (accounts.TryGetValue(username, out password))
{
// use the password
}
serait préférable à ceci:
if (accounts.ContainsKey(username))
{
string password = accounts[username];
}
Et si je voulais vérifier si une clé existait déjà avant de la définir sur une valeur? Par exemple, je voudrais vérifier si un nom d'utilisateur existait avant de le remplacer par un nouveau mot de passe:
if (!accounts.ContainsKey(username))
{
accounts.Add(username, password);
}
else
{
Console.WriteLine("Username is taken!");
}
contre
// this doesn't exist
if (!accounts.TrySetValue(username, password))
{
Console.WriteLine("Username is taken!");
}
Existe-t-il une alternative plus performante à ContainsKey
et Add
qui fait cela?
Si vous ne voulez pas remplacer, je pense qu'il est préférable d'écrire votre propre méthode d'extension comme TryGetValue
. Il n'y a pas de méthode standard.
OR
Utilisez CuncurrentDictionary, il a la méthode TryAdd , mais vous aurez des frais généraux sur la synchronisation.
Donc, réponse simple - non, il n'y a pas une telle méthode.
Si vous pensez que l'insertion d'un nouveau nom sera le cas le plus courant et que la tentative d'insertion d'un doublon sera le cas rare, vous voudrez peut-être simplement utiliser la surcharge pour intercepter une exception.
try
{
accounts.Add(username, password);
}
catch (ArgumentException)
{
Console.WriteLine("Username is taken!");
}
Si vous appelez Add
avec une clé existante, un ArgumentException
sera lancé. Même si vous avez des doublons fréquents, cela sera probablement plus performant que votre contrôle ContainsKey
.
J'ai tendance à écrire mes propres extensions au besoin.
Par exemple, GetValueOrDefault
comme ceci:
public static V GetValueOrDefault<K, V>(this IDictionary<K, V> @this, K key, Func<V> @default)
{
return @this.ContainsKey(key) ? @this[key] : @default();
}
Il peut être utilisé comme ceci:
var password = accounts.GetValueOrDefault(username, () => null);
if (password != null)
{
//do stuff
}
Ou SetValueIfExists
:
public static V SetValueIfExists<K, V>(this IDictionary<K, V> @this, K key, V value)
{
if (@this.ContainsKey(key))
{
@this[key] = value;
}
}
Ou SetValueIfNotExists
:
public static V SetValueIfNotExists<K, V>(this IDictionary<K, V> @this, K key, V value)
{
if ([email protected](key))
{
@this[key] = value;
}
}
Je sais que je suis en retard, mais vous pouvez utiliser une astuce et stocker le nombre avant l'ensemble d'indexeurs et vérifier le nombre après l'ensemble d'indexeurs. Si les nombres sont les mêmes, vous avez remplacé la clé, sinon vous avez ajouté un nouveau mappage:
public static bool AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue>
dictionary, TKey key, TValue value)
{
var countBefore = dictionary.Count;
dictionary[key] = value;
return countBefore != dictionary.Count;
}