2009-06-12 9 views
3

Je suit comme un exemple:meilleure façon d'offrir une table de hachage statique C#

public enum HttpRequestHeader 
{ 
    Accept, 
    AcceptCharset 
} 

public static class HTTP 
{ 
    public static Hashtable HttpRequestHeaderString 
    { 
    get 
    { 
     Hashtable returnHashtable = new Hashtable(); 
     returnHashtable.Add(HttpRequestHeader.Accept,"Accept"); 
     returnHashtable.Add(HttpRequestHeader.AcceptCharset,"Accept-Charset"); 
     return returnHashtable; 
    } 
    } 
} 

J'accéderont:

string HttpRequestHeaderString 
    = HTTP.HttpRequestHeaderStrings[HttpRequestHeader.Accept] 

plusieurs fois. Comme il s'agit d'un staticHashTable, existe-t-il un meilleur moyen de fournir la même fonctionnalité plus efficacement?

Je comprends que je peux mettre en œuvre cette solution particulière en utilisant un type différent de collection, mais si je veux utiliser le HashTable - quelles options sont là pour moi?

Merci beaucoup à l'avance SO!

Répondre

6

Voulez-vous que les appelants puissent muter le dictionnaire? Si c'est le cas, avoir un statique semble une idée très étrange. Si ce n'est pas le cas, vous devez seulement être capable de répondre aux demandes de Accept et AcceptCharset, ce que je ferais probablement dans une simple instruction switch.

Vous dites que vous voulez vraiment utiliser un Hashtable - pourquoi? Quelle est la plus grande image ici?

L'exposition statique de structures de données mutables est presque toujours une mauvaise idée. Si vous voulez une aide à construire une hashtable avec quelques valeurs initiales, alors je ferais une méthode plutôt qu'une propriété. Si vous n'avez pas besoin de mutation, j'écrirais une méthode pour récupérer la valeur d'un HttpRequestHeader plutôt que d'exposer une collection. Par exemple:

public static class HTTP 
{ 
    public static string GetHeaderString(HttpRequestHeader header) 
    { 
     // Use a dictionary here if you want. The API is the important bit 

     switch (header) 
     { 
      case HttpRequestHeader.Accept: return "Accept"; 
      case HttpRequestHeader.AcceptCharset: return "Accept-Charset"; 
      default: throw new KeyNotFoundException(header.ToString()); 
     } 
    } 
} 

Une autre option serait d'avoir un enum Java comme des en-têtes:

public sealed class RequestHeader 
{ 
    public static RequestHeader Accept = new RequestHeader("Accept"); 
    public static RequestHeader AcceptCharset = 
     new RequestHeader("Accept-Charset"); 

    private readonly string name; 

    private RequestHeader(string header) 
    { 
     this. name = name; 
    } 

    public string Name 
    { 
     get { return name; } 
    } 
} 

Vous auriez besoin de faire des vérifications contre null, mais ce serait la seule valeur non valide de RequestHeader que vous pourriez obtenir. (Les énumérations ne sont pas vérifiées par intervalle, donc quelqu'un pourrait facilement écrire ((HttpRequestHeader)-1) dans votre code actuel ... en d'autres termes, il ne résout pas la validation des arguments de toute façon.)

EDIT: En réponse au commentaire, si vous « re en utilisant C# 3 et que vous voulez l'initialisation désireux (pour faciliter la vie), vous pouvez écrire:

public static class HTTP 
{ 
    private static readonly Dictionary<HttpRequestHeader, string> Headers = 
     new Dictionary<HttpRequestHeader, string> 
    { 
     (HttpRequestHeader.Accept, "Accept"), 
     (HttpRequestHeader.AcceptCharset, "Accept-Charset") 
    }; 

    public static string GetHeaderString(HttpRequestHeader header) 
    { 
     return Headers[header]; 
    } 
} 
+0

Eh bien la plus grande image Jon est que J'essaie de produire une classe HttpRequest très fortement typée. Je veux qu'il se conforme strictement aux normes HTTP RFC ..... Donc l'enum HttpRequestHeader est important pour moi. Je ne veux jamais que mon code de niveau supérieur puisse demander une valeur d'en-tête 'chaîne' qui n'est pas présente dans l'énumération HttpRequestHeader .... Je pourrais utiliser une instruction switch, mais je pensais que ce serait bien de voir ce que les gens pensez à ce "modèle". – divinci

+0

Ceci est un exemple extrême - mais disons que j'avais une énumération qui contenait beaucoup de valeurs, par exemple 'TownsOfTheWorld'. Utiliser une instruction switch pour retourner une valeur pour chaque 'TownOfTheWorld' serait plus lent que de les compiler une fois dans un Hastable ?! – divinci

+0

@divinci: Ce serait plus laid, certainement. Notez que je parlais du code exact que vous avez fourni, qui n'a que deux valeurs dans le tableau. Avec plus de valeurs, l'utilisation d'une hashtable a plus de sens. (Bien que la commutation peut être plus efficace, si la clé est une énumération.Notez que si vous essayez de produire une classe "très fortement typée", l'utilisation d'une collection faiblement typée est un mauvais point de départ. –

3

Quel est l'avantage d'une table de hachage vous livrerai écrit ceci:

public static class Http 
{ 
    public const string HttpRequestAccept = "Accept"; 
    public const string HttpRequestAcceptCharset = "Accept-Charset"; 
} 
+0

Cela serait en effet plus rapide - mais une méthode devrait accepter une valeur de chaîne | chaîne publique GetHttpHeaderValue (chaîne HttpHeader) | Je ne veux pas passer des chaînes (même si elles ont été déclarées comme constantes ailleurs). Je veux confiner le paramètre de la méthode 'GetHttpHeaderValue' à une constante. – divinci

Questions connexes