Der C#-Compiler verlangt, dass immer dann, wenn ein benutzerdefinierter Typ den Operator ==
muss sie auch definieren !=
(siehe hier ).
Warum?
Ich bin neugierig, warum die Entwickler dies für notwendig hielten und warum der Compiler nicht auf eine vernünftige Implementierung für einen der beiden Operatoren zurückgreifen kann, wenn nur der andere vorhanden ist. In Lua kann man zum Beispiel nur den Gleichheitsoperator definieren und bekommt den anderen umsonst. C# könnte dasselbe tun, indem es Sie auffordert, entweder == oder sowohl == als auch != zu definieren, und dann den fehlenden !=-Operator automatisch kompiliert als !(left == right)
.
Ich verstehe, dass es seltsame Eckfälle gibt, in denen einige Einheiten weder gleich noch ungleich sein können (wie IEEE-754 NaN's), aber diese scheinen die Ausnahme zu sein, nicht die Regel. Das erklärt also nicht, warum die Entwickler des C#-Compilers die Ausnahme zur Regel gemacht haben.
Ich habe Fälle gesehen, in denen der Gleichheitsoperator definiert wurde und der Ungleichheitsoperator ein Copy-Paste ist, bei dem jeder einzelne Vergleich umgekehrt und jedes && in einen || umgewandelt wurde (Sie verstehen schon... im Grunde !(a==b) erweitert durch De Morgans Regeln). Das ist eine schlechte Praxis, die der Compiler durch Design eliminieren könnte, wie es bei Lua der Fall ist.
Anmerkung: Das Gleiche gilt für die Operatoren < > <= >=. Ich kann mir keine Fälle vorstellen, in denen man diese auf unnatürliche Weise definieren muss. Lua lässt Sie nur < und <= definieren und definiert >= und > auf natürliche Weise durch die Negation der Formers. Warum tut C# nicht dasselbe (zumindest "standardmäßig")?
EDIT
Offensichtlich gibt es triftige Gründe dafür, dem Programmierer zu erlauben, Prüfungen auf Gleichheit und Ungleichheit nach Belieben zu implementieren. Einige der Antworten weisen auf Fälle hin, in denen das gut sein könnte.
Der Kern meiner Frage ist jedoch, warum dies zwangsweise in C# erforderlich ist, wenn in der Regel es ist nicht logischerweise notwendig?
Es steht auch in auffälligem Kontrast zu den Designentscheidungen für .NET-Schnittstellen wie Object.Equals
, IEquatable.Equals
IEqualityComparer.Equals
wo das Fehlen eines NotEquals
Gegenstück zeigt, dass der Rahmen Folgendes berücksichtigt !Equals()
Objekte als ungleich und das war's. Außerdem werden Klassen wie Dictionary
und Methoden wie .Contains()
hängen ausschließlich von den vorgenannten Schnittstellen ab und verwenden die Operatoren nicht direkt, auch wenn sie definiert sind. In der Tat, wenn ReSharper Gleichheitsmitglieder erzeugt, definiert es sowohl ==
y !=
in Bezug auf Equals()
und selbst dann nur, wenn der Benutzer beschließt, überhaupt Operatoren zu erzeugen. Die Gleichheitsoperatoren werden vom Framework nicht benötigt, um Objektgleichheit zu verstehen.
Im Grunde genommen kümmert sich das .NET-Framework nicht um diese Operatoren, es kümmert sich nur um ein paar Equals
Methoden. Die Entscheidung, dass die Operatoren == und != vom Benutzer gemeinsam definiert werden müssen, hat rein mit dem Sprachdesign zu tun und nicht mit der Objektsemantik, soweit es .NET betrifft.
28 Stimmen
+1 für eine ausgezeichnete Frage. Es scheint überhaupt keinen Grund zu geben... natürlich könnte der Compiler davon ausgehen, dass a != b in !(a == b) übersetzt werden kann, solange ihm nichts anderes gesagt wird. Ich bin auch neugierig, warum man sich dazu entschlossen hat, dies zu tun.
0 Stimmen
Wenn es so einfach ist wie
!(left == right)
dann ist das kein Problem für Sie. Wenn die Negation viel komplizierter ist, hat der Compiler keine Chance zu optimieren - aber Sie. Daher ist es nur konsequent, Sie zu zwingen, beide Fälle selbst zu behandeln.3 Stimmen
Die goldene Regel Nr. 1 bei der Entwicklung von Software, APIs und GUIs lautet: Machen Sie immer den Normalfall zum Standard! Es sieht so aus, als hätte das jemand versehentlich nicht getan.
0 Stimmen
@BlueRaja: Ich persönlich bevorzuge einen Compiler, der nicht zu viel selbst denkt, da ich sonst Gefahr laufe, zu vergessen, selbst zu denken, wenn der Compiler Fehler macht.
0 Stimmen
Ich denke, dass nur die Leute, die C# entwickelt haben, diese Frage richtig beantworten können, alles andere ist so ziemlich nur eine Vermutung. In der Tat, ich würde nicht einmal sicher sein, es gibt eine zufriedenstellende Antwort.
0 Stimmen
@BlueRaja: Die goldene Regel für die Entwicklung von Software, APIs und GUIs ist nicht unbedingt die goldene Regel für die Entwicklung von Compilern. Die Priorität des Compilers sollte sein, Laufzeitfehler zu vermeiden, im Zweifelsfall auf Kosten der Bequemlichkeit des Programmierers.
0 Stimmen
Ist es wirklich gesunder Menschenverstand, dass != das Gegenteil von dem sein sollte, was == im Moment implementiert ist? Mir scheint es ebenso vernünftig, anzunehmen, dass die Standardimplementierung von != das Gegenteil der Standardimplementierung von == sein sollte, es sei denn, sie wird außer Kraft gesetzt. Vielleicht ist gesunder Menschenverstand in diesem Fall gar kein gesunder Menschenverstand?
0 Stimmen
Vielleicht war es nur eine Vorsichtsmaßnahme. Wenn Sie mit "Operatoren müssen paarweise auftreten" beginnen, haben Sie die Möglichkeit, auf "fehlende Operatorpartner schließen" umzuschalten. Sie können nicht in die andere Richtung gehen.