2013-04-11 5 views
8

Ho appena avuto un errore di test unitario per uno strano motivo che coinvolge IDictionary<object, object>.In che modo questa risoluzione di sovraccarico ha senso?

IDictionary<K,V> ha due metodi Remove. Uno prende uno K, l'altro prende uno KeyValuePair<K,V>. Considerate queste due dizionari:

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

L'uscita è True, quindi False. Dal KeyValuePair<object,object> è il tipo esatto previsto da d2.Remove(KeyValuePair<object,object>), perché il compilatore chiama invece il d2.Remove(object)?

(post-mortem nota:

Nello scenario che ha spinto la mia domanda, non stavo usando IDictionary<object,object> direttamente, ma piuttosto attraverso un parametro generico:

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

dal momento che il problema è che IDictionary ha preso la priorità su ICollection Ho deciso di "pareggiare" includendo ICollection nell'elenco dei vincoli:

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

ma questo non ha cambiato la mente del compilatore ... Mi chiedo perché no)

+4

IIRC, questo è dovuto a una corrispondenza trovata nel 'tipo di dichiarazione' e non procede al tipo di base. Ho già fatto una domanda simile prima. Alla ricerca di un link Modifica: qui vai: http://stackoverflow.com/q/12242346/15541 (la tua domanda è un duplicato) – leppie

+0

Doh! Beh, non è duplicato al 100% dato che la mia domanda riguarda un'interfaccia generica, giusto? '*' attende l'inevitabile chiusura * – Qwertie

+0

Penso che lo stesso valga per qualsiasi tipo. – leppie

risposta

2

per fornire una soluzione al problema (si veda il commento troppo):.

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

cablato, non ci ho pensato. – Tigran

+0

@Tigran: Sì, mi ha sorpreso anch'io (e non molte cose!) – leppie

+0

Sembra qualcosa che merita un avvertimento per il compilatore, tranne forse no, dal momento che è di progettazione e tutto. Mi chiedo se c'è qualche problema che i progettisti C# intendevano risolvere con questa regola. – Qwertie