Take the 2-minute tour ×

I just had a unit test fail for a strange reason involving IDictionary<object, object>.

IDictionary<K,V> has two Remove methods. One takes a K, the other takes a KeyValuePair<K,V>. Consider these two dictionaries:

IDictionary<string, object> d1 = new Dictionary<string, object>();
IDictionary<object, object> d2 = new Dictionary<object, object>();
d1.Add("1", 2);
d2.Add("1", 2);
Console.WriteLine(d1.Remove(new KeyValuePair<string, object>("1", 2)));
Console.WriteLine(d2.Remove(new KeyValuePair<object, object>("1", 2)));

The output is True, then False. Since KeyValuePair<object,object> is the exact type expected by d2.Remove(KeyValuePair<object,object>), why does the compiler call d2.Remove(object) instead?

(Post-mortem note:

In the scenario that prompted my question, I wasn't using IDictionary<object,object> directly but rather through a generic parameter:

public class DictionaryTests<DictT> where DictT :
    IDictionary<object,object>, new()

since the problem is that IDictionary took priority over ICollection I decided to "even things out" by including ICollection in the list of constraints:

public class DictionaryTests<DictT> where DictT :
    ICollection<KeyValuePair<object, object>>, IDictionary<object,object>, new()

but this didn't change the compiler's mind... I wonder why not.)

share|improve this question
IIRC, this is due to a match being found in the 'declaring type' and it does not proceed to the base type. I asked a similar question before. Looking for link. Edit: Here you go: stackoverflow.com/q/12242346/15541 (your question is a duplicate) –  leppie Apr 11 '13 at 7:27
Doh! Well it's not 100% duplicate since my question is about a generic interface right? *awaits the inevitable closure* –  Qwertie Apr 11 '13 at 14:54
I think the same goes for for any type. –  leppie Apr 11 '13 at 14:56

1 Answer 1

up vote 2 down vote accepted

To provide a solution to the problem (see comment too):

   ((ICollection<KeyValuePair<object, object>) d2).
share|improve this answer
wired, didn't think about this. –  Tigran Apr 11 '13 at 7:37
@Tigran: Yeah, it caught me by surprise too (and not many things do!) –  leppie Apr 11 '13 at 7:42
It seems like something that deserves a compiler warning, except maybe not, since it's by design and all. I wonder if there is some problem that the C# designers intended to solve with this rule. –  Qwertie Apr 11 '13 at 14:58
@Qwertie: Resharper probably does this :) It can't be compiler warning, as the explicit code to make it unambiguous would be overkill. Best not to overload in the inheritance chain. –  leppie Apr 11 '13 at 15:00
@Qwertie: Resharper does not warn about this. –  leppie Apr 11 '13 at 15:12

Your Answer


