Warum können wir Equals () in einem Werttyp ohne Boxen überschreiben?

8

Ich weiß, dass ich Boxen vermeiden kann, indem ich meine eigene Equals-Implementierung hinzufüge.

%Vor%

Ich kann das nicht so sehr als Overload bezeichnen. Durch die Magie der Laufzeit ruft es korrekt die richtige Equals() Implementierung basierend auf dem Typ des Aufrufers auf.

Warum kann ich den Parametertyp nicht auf TwoDoubles überschreiben und ändern und das Boxen bei Bedarf auf der Grundlage der Laufzeit zulassen? Liegt das daran, dass C # die Parameterkontravierung nicht unterstützt (wenn das der Grund ist, warum wird es nicht unterstützt ... scheint ein kleiner Schritt von object o = new TwoDoubles() zu sein)?

UPDATE
Klarstellung: object ist ein Teil der Vererbungshierarchie einer Struktur. Warum können wir keinen abgeleiteten Typ als Parameter angeben, um eine Implementierung von einem weniger abgeleiteten Typ zu überschreiben? Dies würde uns erlauben zu schreiben:

%Vor%

Dies sollte aufgerufen werden, wenn die Variable ein TwoDouble ist, selbst wenn die Variable in einen Objekttyp eingereiht wurde.

    
P.Brian.Mackey 30.04.2012, 21:23
quelle

3 Antworten

13
  

Warum kann ich den Parametertyp nicht auf TwoDoubles überschreiben und ändern?

Weil das nicht typsicher wäre!

%Vor%

Und jetzt hast du einen Tiger an eine Methode übergeben, die eigentlich nur eine Giraffe braucht!

Das Gleiche gilt für Ihren Fall. Sie überschreiben eine Methode, die jedes Objekt mit einer Methode akzeptiert, die nur eine Struktur annehmen kann; das ist nicht typsicher.

  

Liegt das daran, dass C # den Parametertyp contravariance nicht unterstützt?

Nein, weil Sie nach dem Parametertyp Kovarianz fragen, der nicht typsicher ist.

C # unterstützt ebenfalls keine Kontravarianz des Parametertyps, aber das ist nicht das, wonach Sie fragen.

    
Eric Lippert 30.04.2012, 22:50
quelle
2

Sie können den Parameter (Überladung) für Equals genau so ändern, wie Sie es getan haben, und das Boxen wird nach Bedarf ausgeführt (d. h. wann immer Equals (object) aufgerufen wird)

Da alles vom Objekt erbt (oder implizit durch Boxen), können Sie nicht verhindern, dass Personen Equals (Objekt) für Ihren Typ verwenden können. Auf diese Weise erhalten Sie jedoch einen umgangenen Anruf.

Wenn Sie den aufrufenden Code kontrollieren, verwenden Sie immer Ihre neue überladene Option, d. h. Equals(TwoDouble)

Beachten Sie, dass Ihr Code, wie schon ein Kommentator sagte, etwas falsch ist, tun Sie dies stattdessen:

%Vor%

BEARBEITEN wie es klug vorgeschlagen wurde, sollten Sie die gleiche Aufgabe ausführen, aber mithilfe der IEquatable-Schnittstelle, in diesem Fall IEquatable<TwoDouble> (beachten Sie, keine Codeänderung von dem, was wir getan haben, als erforderlich es entspricht der Signatur)

    
payo 30.04.2012 21:38
quelle
2

Wenn es so funktioniert, wie Sie es vorgeschlagen haben, wo public override bool Equals(TwoDoubles c) { return m_Re == c.m_Re && m_Im == c.m_Im; } alles war, was nötig war, um die Methode Equals(object) zu überschreiben, was würde dieser Code tun?

%Vor%

Was soll in Zeile 3 passieren?

  • Soll es Equals(TwoDouble) aufrufen? Wenn ja, mit welchem ​​Parameter? Ein Standard TwoDouble mit allen Nullen? Das würde gegen die Regeln der Gleichheit verstoßen.
  • Soll es eine Ausnahme werfen? Wir haben die Methodensignatur richtig verfolgt, das sollte nicht passieren.
  • Sollte es immer falsch zurückgeben? Nun muss der Compiler wissen, was die Equals-Methode bedeutet , und muss sie anders behandeln als andere Methoden.

Es gibt keine gute Möglichkeit, dies zu implementieren, und es verursacht schnell mehr Probleme, als es löst.

    
David Yaw 30.04.2012 22:16
quelle

Tags und Links