views:

933

answers:

3

I have a class that inherits from Dictionary<string, string>. Within an instance method, I want to iterate over all KeyValuePair<string, string>'s. I've tried doing the following:

foreach (KeyValuePair<string, string> pair in base)

But this fails with the following error:

Use of keyword 'base' is not valid in this context

How can I iterate over the KeyValuePair<string, string>'s in an instance method in a class that derives from Dictionary<string, string>?

Edit: I found I can do the following:

var enumerator = base.GetEnumerator();
while (enumerator.MoveNext())
{
    KeyValuePair<string, string> pair = enumerator.Current;
}

However, I would still like to know if there's a way to do this via a foreach loop.

Edit: thanks for the advice about not inheriting from Dictionary<string, string>. I'm instead implementing System.Collections.IEnumerable, ICollection<KeyValuePair<string, string>>, IEnumerable<KeyValuePair<string, string>>, IDictionary<string, string>.

+10  A: 

First, deriving from the .NET collection classes is generally ill-advised because they don't offer virtual methods for calls not inherited from object. This can result in bugs when passing your derived collection in via a base-class reference somewhere. You are better off implementing the IDictionary<T,TKey> interface and aggregating a Dictionary<,> inside your implementation - to which you then forward the appropriate calls.

That aside, in your specific case, what you want to do is:

foreach( KeyValuePair<string,string> pair in this )  { /* code here */ }

The base keyword is primarily used to access specific members of your base class. That's not what you're doing here - you are attempting to iterate over the items of a particular instance ... which is simply the this reference.

LBushkin
You should sub most in "don't offer virtual methods for most calls" with any :). The only virtual calls they "offer" are teh ones inherrited from object
JaredPar
@JaredPar: I suppose if you discount members inherited from `object` and a few other intervening classes with some virtual methods - you could indeed say that.
LBushkin
+1 for good advice
John K
+1  A: 

I agree with JaredPar's comment that this isn't a great idea. You probably don't want to publicly expose all of the methods of Dictionary to the outside world, so just make the Dictionary a private member variable and then provide your own interface to it.

With that said, the way to do what you're trying to do is:

foreach (KeyValuePair<string, string> pair in this)
Nate C-K
+1  A: 

Encapsulate Dictionary<string, string> as a composed field inside custom class MyDictionary and implement a custom IEnumerable and IEnumerator (or variations thereof) for MyDictionary (or make a method that implements handy C# yield keyword to produce the items)...

E.g.

class MyDictionary : IEnumerable<KeyValuePair<string,string>> {
    Dictionary<string, string> _dict;

    IEnumerator<KeyValuePair<string,string>> GetEnumerator() {
        return new MyEnum(this); // use your enumerator
        // OR simply forget your own implementation and
        return _dict.GetEnumerator();
    } 

    class MyEnum : IEnumerator<KeyValuePair<string,string>> {
        internal MyEnum(MyDictionary dict) {
            //... dict
        }

        // implemented methods (.MoveNext, .Reset, .Current)...

This maintains encapsulation of extraneous methods. And you can still iterate over you instances like so from inside or outside:

// from outside
MyDictionary mdict = new MyDictionary();
foreach (KeyValuePair<string, string> kvp in mdict)
    //...

// from inside, assuming: this == MyDictionary instance)
public void MyDictionaryMethod() {
    foreach (KeyValuePair<string, string> kvp in this)
        //...
John K