2010-04-27 4 views
8

Tout ce que je veux, c'est un dictionnaire qui me dit quelle clé il n'a pas pu trouver, plutôt que de simplement dire The given key was not present in the dictionary. J'ai brièvement envisagé de faire une sous-classe avec override new this[TKey key], mais j'ai trouvé que c'était un peu hack, donc j'ai mis en place l'interface IDictionary, et j'ai passé tout directement à un dictionnaire interne, avec la seule logique supplémentaire dans le indexeur:"Verbose Dictionary" en C#, 'redéfinir nouveau' this [] ou implémenter IDictionary

public TValue this[TKey key] 
{ 
    get 
    { 
     ThrowIfKeyNotFound(key); 
     return _dic[key]; 
    } 
    set 
    { 
     ThrowIfKeyNotFound(key); 
     _dic[key] = value; 
    } 
} 
private void ThrowIfKeyNotFound(TKey key) 
{ 
    if(!_dic.ContainsKey(key)) 
     throw new ArgumentOutOfRangeException("Can't find key [" + key + "] in dictionary"); 
} 

Est-ce le droit/seulement aller? Est-ce que le fait de se réjouir de ce [] serait vraiment si mauvais?

Répondre

10

sonne comme un bon moyen pour une méthode d'extension:

public static class SomeUtilClass { 
    public static TValue VerboseGetValue<TKey, TValue>(
     this IDictionary<TKey, TValue> data, TKey key) 
    { 
     TValue result; 
     if (!data.TryGetValue(key, out result)) { 
      throw new KeyNotFoundException(
       "Key not found: " + Convert.ToString(key)); 
     } 
     return result; 
    } 
} 

Ce sera alors travailler sur tous vos dictionnaires existants chaque fois que vous appelez VerboseGetValue, par exemple:

var data = new Dictionary<int, string> { { 123, "abc" } }; 
    Console.WriteLine(data.VerboseGetValue(123)); 
    Console.WriteLine(data.VerboseGetValue(456)); 
+0

Je suis tellement content que les utilisateurs # 1 et # 2 soient du bon côté de la planète :) – Benjol

1

Si vous voulez faire cela, vous devrez rouler le vôtre d'une manière ou d'une autre. Mais je vais demander pourquoi vous voulez faire cela?

+0

Eh bien, je pensais que je l'ai dit pourquoi dans la question. Mais plutôt que de recevoir un mail du gars en train de dire "quelle valeur ai-je eu?", Je préfère qu'il puisse le réparer lui-même. – Benjol

3

Au lieu de faire ContainsKey et vérifier la présence de la clé avant de toucher le dictionnaire sous-jacente, pourquoi ne pas faire

get { 
    try { 
     return _dic[key]; 
    } 
    catch (ArgumentOutOfRangeException) { 
     throw new ArgumentOutOfRangeException(......); 
    } 
} 

De cette façon, vous ne payez que pour la vérification supplémentaire dans le cas d'échec - le cas de succès , qui, espérons-le plus commun, n'a pas à faire une recherche de dictionnaire supplémentaire. C'est bon pour get, mais set est plus difficile car le comportement par défaut de set est de toujours fonctionner. Si vous ne le souhaitez pas, vous devrez d'abord vérifier l'existence de la clé.

+0

+1 Un gestionnaire d'exceptions est le meilleur moyen de gérer une condition exceptionnelle. C'est ce qu'ils sont pour. :) – HiredMind

+1

@Stewart À moins que je ne me trompe, 'System.Collections.Generic.Dictionary' ne jette pas une erreur dans l'indexeur quand la clé n'a pas été trouvée, à la place il est ajouté silencieusement avec la nouvelle valeur. Votre approche fonctionnerait quand même pour le getter. –

+0

@ GeorgesDupéron - Vous avez raison. Cela ne fonctionne que dans le cas get. Je vais modifier l'exemple. Pour le cas d'ensemble, la vérification supplémentaire est inévitable. – Stewart

Questions connexes