2016-02-03 11 views
5

In un programma sensibile alle prestazioni, sto tentando di chiamare esplicitamente IEquatable<T>.Equals() e non Object.Equals (per evitare la boxe nel mio caso). Nonostante i miei migliori sforzi, il compilatore sceglie sempre Object.Equals() - che non capisco. Una classe esempio inventato:Selezione del sovraccarico errata chiamata di sovraccarico IEquatable <T>. Equals

class Foo : IEquatable<Foo> 
{ 
    public bool Equals(Foo f) 
    { 
     Console.WriteLine("IEquatable.Equals"); 
     return true; 
    } 

    public override bool Equals(object f) 
    { 
     Console.WriteLine("Object.Equals"); 
     return true; 
    } 
} 

codice Altrettanto artificiosa che illustra il problema:

// This calls IEquatable<Foo> 
Foo f = new Foo(); 
f.Equals(f); 

// This calls Object.Equals 
IEquatable<Foo> i = new Foo(); 
i.Equals(i); 

L'uscita di questo codice è:

IEquatable.Equals 
Object.Equals 

ho letto di article on overloading Jon Skeet ed è venuto fuori ancora non capisco il problema qui. Quindi la mia domanda è, come faccio a chiamare esplicitamente IEquatable<Foo>.Equals sulla variabile i sopra?

+6

A 'Foo' ** IS ** an' IEquatable '. Un 'IEquatable ' ** NON è ** un 'Foo'. Questo rende più chiaro il motivo per cui questo funziona come fa - in particolare, perché 'public bool Equals (Foo f)' non può essere chiamato con un 'IEquatable '? –

+0

Se sei sicuro che 'i' * è * a' Foo', quindi 'i.Equals ((Foo) i);'. Ma, naturalmente, se sei sicuro del suo tipo, quando non è il tipo dichiarato di "i"? –

+1

Su una nota non correlata, posso solo dire che questa è una bella prima domanda - hai dato una chiara dichiarazione del tuo problema, codice riproducibile, output, una chiara dichiarazione del risultato atteso, e infine, dimostrazione di ricerca indipendente - avere un upvote e benvenuti a Stack Overflow :) –

risposta

5

Il motivo per cui il secondo sovraccarico scelto è irrilevante per il tipo del chiamante. Piuttosto è rilevante per il tipo di argomento che stai passando a Equals. Quindi, anche se chiami il numero f.Equals(i), verrà scelto il metodo object.Equals. La ragione è semplice, il compilatore cerca il sovraccarico più appropriato. Dal momento che il IEquatable<Foo> non deve necessariamente essere Foo, perché esiste forse un altro tipo, diciamo Bar che implementa IEquatable<Foo>, in tal caso non sarebbe corretto (o possibile) scegliere il sovraccarico Equals(Foo f).

Dal momento che il compilatore non controlla il tipo sottostante di IEquatable<Foo>, è necessario lanciare in modo esplicito il parametro Foo se si desidera chiamare Equals(Foo) sovraccarico.

+0

Grazie per l'ottima spiegazione. Questo ha perfettamente senso e mi ha sbloccato. – Tom19

Problemi correlati