Frage

Ich fand diese Methode gültig, aber ich habe mich geirrt:

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

Nach dem Lesen der Spezifikation (§7.2.4 in v3.0 und §7.3.4 in v4.0):

7.2.4 Überlastungsauflösung von Binärbetreiber

Eine Operation des Formulars X OP Y, wobei OP ein überladbarer Binäroperator ist, X ist ein Ausdruck von Typ x und y Ausdruck vom Typ Y Y, wird wie folgt verarbeitet:

  • Die von X und Y für den Operator Operator OP (x, y) bereitgestellte Menge der von X und Y bereitgestellten Kandidatenbetreiber. Das Set besteht aus der Vereinigung der von x bereitgestellten Kandidatenbetreiber und den von Y bereitgestellten Kandidatenbetreibern, die jeweils unter Verwendung der Regeln von §7.2.5 bestimmt wurden. Wenn x und y der gleiche Typ sind oder wenn x und y von einem gemeinsamen Basistyp abgeleitet sind, treten gemeinsam genutzte Kandidatenbetreiber nur einmal im kombinierten Satz auf.

  • Wenn die Menge der benutzerdefinierten Operatoren von Kandidaten nicht leer ist, wird dies zum Satz der Kandidatenbetreiber für den Betrieb. Andernfalls werden die vordefinierten Binärbetreiber -OP -Implementierungen, einschließlich ihrer aufgehobenen Formulare, zum Satz der Kandidatenbetreiber für den Betrieb. Die vordefinierten Implementierungen eines bestimmten Operators sind in der Beschreibung des Bedieners angegeben (§7.7 bis §7.11).

  • Die Überlastungsregeln von §7.4.3 werden auf die Menge der Kandidatenbetreiber angewendet, um den besten Operator in Bezug auf die Argumentliste (x, y) auszuwählen, und dieser Bediener wird zum Ergebnis des Überlastauflösungsprozesses. Wenn die Überlastauflösung keinen einzigen besten Operator auswählt, tritt ein Kompilierungs-Zeitfehler auf.

In Schritt 2 denke ich, dass diese vordefinierte Implementierung angewendet werden sollte:

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

Da alles in C# aus dem Objekt stammt. Wie kann in Schritt 3 ein Kompilierungszeitfehler auftreten? Ich denke nicht, dass es möglich ist, dass "Überlastauflösung in diesem Fall nicht ausgewählt wird".

BEARBEITEN Die Frage kam mir in den Sinn, als ich so etwas umsetzte:

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

Ich fürchte, ich muss einen Ausdruck aufbauen und ihn dynamisch aufrufen Equals Methode.

War es hilfreich?

Lösung

Gut für Sie für das Lesen der Spezifikation, aber Sie haben zu früh aufgehört zu lesen. Hätten Sie weiter gelesen, wären Sie zu diesem Stück gekommen:


Die vordefinierten Referenztyp -Gleichstellungsoperatoren erfordern eines der folgenden:

  • Beide Operanden sind ein Wert eines Typs, von dem bekannt ist, dass es sich um einen Referenztyp oder ein wörtlicher Null handelt. Darüber hinaus besteht eine explizite Referenzumwandlung aus der Art von Operanden zum Typ des anderen Operanden.

  • Ein Operand ist ein Wert von Typ T, bei dem T ein Typ-Parameter und der andere Operand der wörtliche Null ist. Darüber hinaus hat t nicht die Wertschöpfungsbeschränkung.

Sofern eine dieser Bedingungen nicht wahr ist, tritt ein Bindungs-Zeit-Fehler auf. (*)


Der Fehler stammt aus einer Überlastauflösung. Der Fehler ist, dass die Überlastauflösung den vordefinierten Referenztyp -Gleichstellungsoperator gewählt hätte und Sie keine Referenztypen haben.

Betrachten Sie Ihren Code. Was hindert T davon, ein Werttyp zu sein, ohne dass der Gleichstellungsoperator definiert ist? Nichts. Angenommen, wir sind auf die Objektversion zurückgefallen; Beide Operanden würden an verschiedenen Standorten boxen und daher referenzunabhängig sein, auch wenn sie den gleichen Inhalt hätten. Da das langsam, verwirrend und falsch ist, ist es illegal, überhaupt zu versuchen.

Warum versuchst du das überhaupt zu tun? Wenn Ihre Methode funktioniert, was dies nicht der Fall ist, wäre Ihre Methode schlechter als einfach nur mit ==. Was ist der Wert, den Sie mit dieser Methode der Welt hinzufügen möchten?


.

Andere Tipps

Das würde möglicherweise funktionieren, wenn es das wüsste where T : class, einen Referenzvergleich durchführen. Die Betreiber haben im Allgemeinen nur sehr wenig Unterstützung bei Generika, aber es gibt Problemumgehungen. Miscutil Angebote indirekte Unterstützung für die Betreiber auf Generika, sonst EqualityComparer<T>.Default.Equals(x,y) ist eine gute Wahl.

Ich mag es zu benutzen EqualityComparer<T>.Default dafür.

Es basiert auf dem überschriebenen Equals Methode, verwendet aber IEquatable<T> Wenn verfügbar, vermeiden Sie das Boxen auf Werttypen, die es implementieren.

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

verwenden .Equals() Methode und sicherstellen, dass die T implementieren IComparable

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top