views:

1210

answers:

2

Hi all!

I have the following as an example:

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;
    }
  }
}

I will be accessing :

string HttpRequestHeaderString
    = HTTP.HttpRequestHeaderStrings[HttpRequestHeader.Accept]

many times. As this is a static HashTable, is there a better way of providing the same functionality more efficiently?

I understand that I can implement this particular solution using a different type of collection, but if I want to use the HashTable - what options are there for me?

Many thanks in advance SO!

+6  A: 

Do you want callers to be able to mutate the dictionary? If so, having a static one sounds like a very odd idea. If not, you really only need to be able to response to requests for Accept and AcceptCharset, which I'd probably do in a simple switch statement.

You say you really want to be use a Hashtable - why? What's the bigger picture here?

Exposing mutable data structures statically is almost always a bad idea. If you want a helper to build a hashtable with some initial values, then I'd make it a method rather than a property. If you don't need mutation, I'd write a method to fetch the value for a specific HttpRequestHeader rather than exposing a collection. For example:

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());
        }
    }
}

Another option would be to have a Java-like enum of headers:

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; }
    }
}

You'd need to do checks against null, but that would be the only invalid value of RequestHeader that you could get. (Enums aren't range-checked, so someone could easily write ((HttpRequestHeader)-1) in your current code... in other words, it doesn't fix argument validation anyway.)

EDIT: In response to the comment, if you're using C# 3 and want eager initialization (to make life easier) you could write:

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];
    }
}
Jon Skeet
Well the bigger picture Jon is that I am trying to produce a very strongly typed HttpRequest class. I want it to conform strictly to the HTTP RFC standards..... So the HttpRequestHeader enum is important to me. I never want my higher level code to be able to request a 'string' header value that is not present in the HttpRequestHeader enum....I could of used a switch statement I know,but thought it would be good to see what people think about this 'pattern'.
divinci
This is an extreme example - but say I had an enum that contained a lot of values e.g 'TownsOfTheWorld'. Using a switch statement to return a value for each 'TownOfTheWorld' would be slower than compiling them ONCE into a Hastable?!
divinci
@divinci: It would be uglier, certainly. Notice that I was talking about the exact code you'd provided, which only has two values in the table. With more values, using a hashtable makes more sense. (Although switching may actually be more efficient, if the key is an enum.) Note that if you're trying to produce a "very strongly typed" class, using a weakly typed collection is a bad starting point.
Jon Skeet
@Jon, so if I replaced this Hashtable with a Dictionary and ignored the performance hit. How do I initialise it with values for later static access?
divinci
@Jon - thanks for your input! - I will be a programmer one day!
divinci
@divinci: Edited answer to show that...
Jon Skeet
+1: Informative, helpful response as usual.
Juliet
+3  A: 

What advantage does a hashtable give you over writing this:

public static class Http
{
    public const string HttpRequestAccept = "Accept";
    public const string HttpRequestAcceptCharset = "Accept-Charset";
}
Juliet
This would indeed be quicker - but a method would have to accept a string value | public string GetHttpHeaderValue(string HttpHeader) | I do not want to be passing strings (even if they have been declared as constants elsewhere). I want to confine the 'GetHttpHeaderValue' method's parameter to a constant.
divinci