views:

1171

answers:

3

Sorry to ask this yet again. I've been reading the related topics here for hours and still don't quite get some of the issues with casting and generics. I'm trying to create our own HashSet class, because we can't use .net 3.5 yet.

The error is in the RetainAll method, below. It compiles fine but I get a runtime error 'Unable to cast object of type 'System.Collections.DictionaryEntry' to type 'mycompany.UnivID' on the foreach statement.

Does this mean I can't cast a generic object to its implementing type? I've tried a couple things like

foreach ((T) obj in set)

but they don't compile.

Relevant code is:

public sealed class HashSet<T> : ISet<T> {

  private readonly Hashtable set;

  public HashSet() {
    this.set = new Hashtable();
  }

  public void RetainAll(ISet<T> c) {
    lock (set) {
      foreach (T obj in set) {
        if (!c.Contains(obj))
          this.set.Remove(obj);
      }
    }
  }
}

The implementing class snippet is

public sealed class UnivIDSet : ISet {
  private readonly ISet<UnivID> univIDs;

  public UnivIDSet() : base() {
    univIDs = new HashSet<UnivID>();
  }
}

and then we've got our UnivID class which are actually the objects in the sets.

+4  A: 

I think

foreach (T obj in set) {

should be

foreach (T obj in set.Values) {
Mladen Mihajlovic
yes, that was it. Thanks! I'm a bit embarrassed now by the question. I should have known or been able to figure it out.
Ha ha, happens to all of us. Sometimes another pair of eyes helps.
Mladen Mihajlovic
A: 

When you enumerate a HashTable the type the enumerator returns is a DictionaryEntry. Read the Key and Value properties of this object to get what you need.

pipTheGeek
A: 

Hashtables map keys to values. When you iterate over each item in the hashtable, that item is a key/value pair (that's what the DictionaryEntry class is). You probably want to iterate over the Keys property or the Values property instead, depending on how you entered things into the table.

Also note that the Dictionary class is the generic version of a hashtable, so it's probably worth building your HashSet on top of that instead.

kvb