views:

658

answers:

5

I need to define a class with an internal collection object to hold different types of values(such as string, int, float, DateTime, and bool) by a string key. I could use Hashtable since it is not strongly typed collection class, while the Dictionary is used for strongly typed items (I could use object for Dictionary even though).

Here is the case I would like to define my class and its usage:

 public class MyBaseClass<D> {
   protected Hashtable ht = new Hashtable();

   MyClass public SetValue<T>(string key, T value)
   {
       ht.Add(key, value);
       return this;
   }

   public abstract D GetObject();
 }

 // Example of using the base class for data as class Data1
 public MyClass<Data1> : MyBaseClass<Data1> {
      public Data1 GetObject() {
         return new Data1 {
             Property1 = ht["key1"] as string,
             Property2 = Int.Parse(ht["key2"].ToString())
          }
 }

With above example, I am not sure what is the best collection to hold my data in MyBaseClass? I read some articles about Hashtable. It is an obsolete collection and the performance comparing to Dictionary collection is much slower. Should I use Dictionary or any other collection available in .Net 3.5?

+4  A: 

You should always use generic collections, unless there is a very good reason not to. This ensures everything is reasonably type safe and reduces programming errors. There are also performance benefits if you store value types in the generic dictionary; if you use Hashtable, each value type would have to be boxed.

Your example, however, seems inherently type-unsafe, and has a code smell about it. Is there a particular reason why you've got two type variables to access the same hashtable?

thecoop
+8  A: 

Personally I'd use Dictionary<string, object> in this case. At the very least this will stop you from trying to use a non-string key.

I would personally stop using a protected field as well - consider adding an indexer to your base class with a protected setter and a public getter:

public object this[string key]
{
    get { return ht[key]; }
    protected set { ht[key] = value; }
}

If you want it to return null on access by missing key, you should use TryGetValue in the getter. Likewise you could use Add in the setter if you want to fail on duplicate key addition.

Jon Skeet
actually in this case, I don't care about null or exception. I would like to get exception in case I try get a value what is not set yet.
David.Chu.ca
In that case the code I posted would be fine. If you use the same key twice for *setting* it will just overwrite the previous value though.
Jon Skeet
@Jon Skeet, thank you for your info. I may use this override feature to read another set of properties and then create a new obj based on the new set data. In order words, I can reuse the instance in a loop or method call (loop or method call is kind of repeat with different values).
David.Chu.ca
A: 

I would go with the Dictionary. I can think of only one scenario where a Hashtable might be preferred. It is thread-safe for one writer and multiple readers without using synchronization mechanisms. But, such a scenario would be very specific and quite rare. And even then I would probably go with the Dictionary and use all of the normal synchronization primitives.

Brian Gideon
A: 

I would use a Dictionary, but I really wanted to make my collection typesafe, I might implement the type-safe heterogeneous container described in Item 29 of Effective Java (the example is for Java, but the application should work for both languages although the details and restrictions may differ). This technique encodes the type of the value into the key.

Kathy Van Stone
A: 

Hashtable existed in 1.1. Dictionary did not exist until generics came in in 2.0. I don't think there's any reason to use Hashtable in 2.0 and beyond - it's essentially a hardcoded Dictionary<string,object> , and it's (probably?) just there to let ported 1.1 code work.

So, Dictionary should be your object of choice here.

quillbreaker