2011-04-27 13 views
11

Ho pensato che questo metodo era valido, ma mi sbagliavo:L'operatore '==' non può essere applicato al tipo T?

static void Equals<T>(T x, T y) 
{ 
    return x == y; //operator == can't be applied to type T 
} 

Dopo aver letto la specifiation (§7.2.4 in v3.0 e §7.3.4 in v4.0):

7.2.4 operatore binario risoluzione sovraccarico

un'operazione del modulo x op y, dove op è un operatore binario sovraccaricabile, x è un'espressione di tipo x e Y è un'espressione di tipo Y, viene elaborato come segue:

  • L'insieme di candidati operatori definiti dall'utente fornite da X e Y per l'operatore op operazione (x, y) è determinata. Il set consiste nell'unione degli operatori candidati forniti da X e gli operatori candidati forniti da Y, ciascuno determinato utilizzando le regole di §7.2.5. Se X e Y sono dello stesso tipo, o se X e Y sono derivati ​​da un tipo base comune, quindi condivisi operatori candidati si verificano solo in combinata di una volta.

  • Se l'insieme di candidati operatori definiti dall'utente è non vuota, allora questo diventa il set di operatori candidati l'operazione . In caso contrario, le implementazioni op operatorie binarie predefinite, compresi i moduli revocati, diventano l'insieme di operatori candidati per l'operazione . Predefiniti implementazioni di un determinato operatore sono specificate nella descrizione dell'operatore (§7.7 attraverso §7.11).

  • Le regole di risoluzione di sovraccarico di §7.4.3 vengono applicate all'insieme di operatori candidati per selezionare l'operatore migliore rispetto all'elenco di argomenti (x, y) e questo operatore diventa il risultato del processo di risoluzione del sovraccarico . Se la risoluzione del sovraccarico non riesce a selezionare un singolo miglior operatore, si verifica un errore in fase di compilazione.

Al punto 2 Penso che questa implementazione predefinita dovrebbe essere applicato:

bool operator ==(object x, object y); 
bool operator !=(object x, object y); 

dato che tutto in C# deriva da Object. Come può verificarsi un errore di compilazione nel passaggio 3? Non penso sia possibile che "la risoluzione di sovraccarico non riesca a selezionare" in questo caso.

EDIT La domanda è venuta in mente quando mi stava realizzando qualcosa di simile:

class EnumComparer<TEnum> : IEqualityComparer<TEnum> 
{ 
    public bool Equals(TEnum x, TEnum y) 
    { 
     return x == y; 
    } 
    public int GetHashCode(TEnum obj) 
    { 
     return (int)obj; 
    } 
} 

ho paura Ho bisogno di costruire un espressione e invocarlo dynamicly in Equals metodo.

+0

possibile duplicato del [C# confrontano due valori generici] (http://stackoverflow.com/questions/488250/c-compare-two-generic-values) –

+0

FWIW, '(oggetto) x == (oggetto) y' è valido - ma considera '(oggetto) 1 == (oggetto) 1' come motivo per non desiderarlo. Ho solo bisogno di aiutare 'T' insieme a un non generico. –

+1

La discussione è un po 'astratta, ma Eric Lippert ha sottolineato che è un malinteso generale che tutto * derivi * da "Oggetto". http://blogs.msdn.com/b/ericlippert/archive/2009/08/06/not-everything-derives-from-object.aspx Un punto rilevante che menziona è che i parametri di tipo non derivano da nulla. –

risposta

20

Buon per te per aver letto le specifiche, ma hai smesso di leggere troppo presto. Dovuto leggere più si sarebbe ottenuto a questo bit:


Gli operatori di uguaglianza del tipo di riferimento predefinite richiedono una delle seguenti operazioni:

  • entrambi gli operandi sono un valore di tipo noto per essere un tipo di riferimento o il valore letterale nullo. Inoltre, esiste una conversione di riferimento esplicita dal tipo di entrambi gli operandi al tipo di altro operando.

  • Un operando è un valore di tipo T in cui T è un parametro di tipo e l'altro è il valore letterale nullo. Inoltre T non ha il vincolo del tipo di valore.

A meno che una di queste condizioni sia vera, si verifica un errore di tempo di associazione. (*)


L'errore non è da risoluzione sovraccarico; l'errore è che la risoluzione di sovraccarico avrebbe scelto l'operatore di uguaglianza di tipo di riferimento predefinito e non si dispone di tipi di riferimento.

Considera il tuo codice. Cosa impedisce a T di essere un tipo di valore senza operatore di uguaglianza definito su di esso? Niente. Supponiamo di ricorrere alla versione dell'oggetto; entrambi gli operandi si posizionerebbero in posizioni diverse e quindi sarebbero di riferimento-non uguali, anche se avessero lo stesso contenuto. Dal momento che è lento, confuso e sbagliato, è illegale persino provare.

Perché stai provando a fare questa cosa in primo luogo? Se il tuo metodo ha funzionato, quale no, allora il tuo metodo sarebbe peggiore di rispetto al semplice utilizzo di == in primo luogo. Qual è il valore che intendi aggiungere al mondo con questo metodo?


(*) Ho segnalato l'errore grammaticale in questa frase per i manutentori spec.

+0

Grazie per la risposta. Vedi la mia modifica per sapere come mi viene in mente questa domanda. –

+0

Vedi domanda correlata: http://stackoverflow.com/questions/5829441/equalitycomparert-default-isnt-clever-enough –

-1

uso .Equals() metodo ed essere sicuri che il T attrezzo IComparable

+6

'IComparable []' è * ordering *; Uguale (con 'GetHashCose()' e opzionalmente 'IEquatable ') è l'uguaglianza. –

+1

Typo: GetHashCode –

7

che avrebbe potuto funzionare se sapesse che where T : class, facendo un confronto di riferimento. Gli operatori generalmente hanno pochissimo supporto con i generici, ma ci sono soluzioni alternative. MiscUtil offre indirect support for operators su generici, altrimenti EqualityComparer<T>.Default.Equals(x,y) è una buona scelta.

+0

Grazie! Voglio solo implementare un confronto per le enumerazioni. Vedi la mia modifica. –

+4

@Danny - prova 'EqualityComparer .Default.Equals (x, y)' then –

+0

LOL! Ero nella direzione sbagliata! Grazie mille per il suggerimento! –

1

Mi piace usare EqualityComparer<T>.Default per questo.

Si basa sul metodo sostituito Equals, ma utilizza IEquatable<T> quando disponibile, evitando il pugilato sui tipi di valore che lo implementano.

EqualityComparer<T>.Default.Equals(x, y) 
Problemi correlati