views:

683

answers:

4

I'm not sure what I'm wanting to do is even a good idea, but here's the problem anyway: I have MyClass which I want to implement two different types of the generic IEnumerable class, e.g.

public class MyClass : IEnumerable<KeyValuePair<string, string>>,
                       IEnumerable<KeyValuePair<MyEnum, string>>

Now, the problem with doing this is when I try to define necessary methods from the interfaces, the compiler complains "Type 'MyClass' already defines a member called 'GetEnumerator' with the same parameter types". This is because I have these two methods:

public IEnumerator<KeyValuePair<MyEnum, string>> GetEnumerator() { ... }
public IEnumerator<KeyValuePair<string, string>> GetEnumerator() { ... }

I have to have GetEnumerator() with no parameters because of the interface, and the only thing that differs is the return type, which is not allowed.

Here are what I see as my options:

  1. I was considering having a "main" IEnumerable generic type which MyClass would implement, and then just adding extra methods that differ by parameters and not just return type (e.g. Add), without implementing the extra generic interfaces.
  2. I could create a generic base class for MyClass, call it MyBaseClass<T>, and it would implement IEnumerable<KeyValuePair<T, string>>. Then, I would have different versions of MyClass, e.g. MyClass<string> and MyClass<MyEnum>.

Which seems preferable here, or am I missing something that would be an even better solution?

+2  A: 

You can explicity implement each interface like this:

IEnumerable<KeyValuePair<string, string>> IEnumerable<KeyValuePair<string, string>>.GetEnumerator() { ... }
IEnumerator<KeyValuePair<MyEnum, string>> IEnumerator<KeyValuePair<MyEnum, string>>.GetEnumerator() { ... }
Charlie
+2  A: 

You can use explicit interface implementation to implement interfaces with conflicting methods. However, if you implement two IEnumerable<T> interfaces, it will cause some rather annoying issues for things like foreach loops. I once tried this for something and promptly went back to implementing 1 IEnumerable interface, and offering the other as a property of the object.

280Z28
5 answers about explicit interfaces in 2 minutes. :D
Arnis L.
Yes, but only mine offers an improved solution :deal: :)
280Z28
I won't participate in "who will improve his answer better" race. :)
Arnis L.
+11  A: 

You can use explicit interface declarations in order to get different implementations for each of the two interfaces that you are implement. For example:

public class MyClass : IEnumerable<KeyValuePair<string, string>>,
                   IEnumerable<KeyValuePair<MyEnum, string>>
{
    IEnumerator<KeyValuePair<MyEnum, string>> IEnumerable<KeyValuePair<MyEnum, string>>.GetEnumerator()
    {
        // return your enumerator here
    }

    IEnumerator<KeyValuePair<string, string>> IEnumerable<KeyValuePair<string, string>>.GetEnumerator()
    {
        // return your enumerator here
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        var me = this as IEnumerable<KeyValuePair<string, string>>;
        return me.GetEnumerator();
    }
}

However, because IEnumerable<> derives from IEnumerable, you'll have to pick which one you want to return from the IEnumerable.GetEnumerator() call.

scwagner
A: 

One option would be to implement interfaces explicitly.

Downside - you would always need to cast MyClass.

Arnis L.