2013-04-11 11 views
8

Po prostu test jednostkowy zakończył się niepowodzeniem z dziwnego powodu z udziałem IDictionary<object, object>.Jak ta rozdzielczość przeciążania ma jakiś sens?

IDictionary<K,V> ma dwie metody: Remove. Jedna zajmuje K, druga zajmuje KeyValuePair<K,V>. Rozważmy te dwa słowniki:

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))); 

Wyjście jest True, następnie False. Ponieważ KeyValuePair<object,object> jest dokładnym typem oczekiwanym przez d2.Remove(KeyValuePair<object,object>), dlaczego zamiast tego kompilator wywołuje d2.Remove(object)?

(Pośmiertne uwaga:

W scenariuszu, które spowodowały moje pytanie, ja nie używałem IDictionary<object,object> bezpośrednio, lecz za pośrednictwem parametru rodzajowego:

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

ponieważ problem jest to, że IDictionary miało pierwszeństwo przed ICollection Postanowiłem "wyrównać rzeczy", włączając ICollection na liście ograniczeń:

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

ale to nie zmieni zdanie kompilator za ... Zastanawiam się dlaczego nie)

+4

IIRC, jest to spowodowane do znalezienia w "rodzaju deklaracji" i nie przechodzi do typu bazowego. Zadałem już podobne pytanie. Szukam łącza. Edycja: Tutaj możesz: http://stackoverflow.com/q/12242346/15541 (twoje pytanie jest duplikatem) – leppie

+0

Doh! Cóż, to nie jest w 100% duplikat, ponieważ moje pytanie dotyczy ogólnego interfejsu? '*' czeka na nieuchronne zamknięcie * – Qwertie

+0

Myślę, że to samo dotyczy każdego typu. – leppie

Odpowiedz

2

Aby zapewnić rozwiązanie problemu (patrz komentarz zbyt).

Console.WriteLine( 
    ((ICollection<KeyValuePair<object, object>) d2). 
     Remove(new KeyValuePair<object, object>("1", 2))); 
+0

przewodowy, nie myślałem o tym. – Tigran

+0

@ Tigran: Tak, to mnie zaskoczyło (i niewiele się dzieje!) – leppie

+0

Wydaje się, że coś, co zasługuje na ostrzeżenie kompilatora, może z wyjątkiem tego, ponieważ jest zgodne z projektem i wszystkim. Zastanawiam się, czy jest jakiś problem, który projektanci C# zamierzali rozwiązać za pomocą tej reguły. – Qwertie

Powiązane problemy