Question

I'm trying to port some code that uses Hashtable to an environment that doesn't have this class. So I thought about not messing with the code and just create my own Hashtable from Dictionary, like this:

public class Hashtable : Dictionary<Object, Object> {
    // ...
    new public IDictionaryEnumerator GetEnumerator() {          

      var ie = base.GetEnumerator();
      while (ie.MoveNext())
          yield return new DictionaryEntry(ie.Current.Key, ie.Current.Value);
    }
}

I'm getting this error:

error CS1624: The body of 'System.Collections.Hashtable.GetEnumerator()' cannot be an iterator block because 'System.Collections.IDictionaryEnumerator' is not an iterator interface type

Well, but IDictionaryEnumerator inherits from IEnumerator.

The odd thing is that if I just return (IDictionaryEnumerator)base.GetEnumerator(); the code compiles (but fails during runtime in the foreach loop).

I don't understand what this error is telling me and don't know how to properly implement this.

Was it helpful?

Solution

Iterator blocks are rewritten by the compiler into classes that implement IEnumerable or IEnumerator; the compiler doesn't know how to generate a class that implement IDictionaryEnumerator, so you can't use an iterator block to implement that interface.

A possible workaround is to provide your own implementation of IDictionaryEnumerator:

class Hashtable : Dictionary<object, object>
{
    new public IDictionaryEnumerator GetEnumerator()
    {
        return new DictionaryEnumerator(base.GetEnumerator());
    }

    struct DictionaryEnumerator : IDictionaryEnumerator
    {
        private Enumerator _en;

        public DictionaryEnumerator(Dictionary<object, object>.Enumerator en)
        {
            _en = en;
        }

        public object Current
        {
            get
            {
                return Entry;
            }
        }

        public DictionaryEntry Entry
        {
            get
            {
                var kvp = _en.Current;
                return new DictionaryEntry(kvp.Key, kvp.Value);
            }
        }

        public bool MoveNext()
        {
            bool result = _en.MoveNext();
            return result;
        }

        public void Reset()
        {
            throw new NotSupportedException();
        }

        public object Key
        {
            get
            {
                var kvp = _en.Current;
                return kvp.Key;
            }
        }

        public object Value
        {
            get
            {
                var kvp = _en.Current;
                return kvp.Value;
            }
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top