Ein Beispiel wäre:
%Vor%Warum nicht?:
%Vor%Was ist die Idee dahinter, implizite / explizite Konvertierungen anstelle von Konstruktoren zu verwenden? Bequemlichkeit?
Gibt es dafür eine Richtlinie?
Bequemlichkeit?
Mehr oder weniger, ja. Betrachten Sie den Fall, wenn Sie ein zahlenähnliches Objekt (z. B. Complex
) haben, für das Sie Berechnungen durchführen. Klar, Code schreiben wie:
ist sehr nervig und schwer zu lesen. Implizite Konvertierungen helfen hier (eine Alternative wären Operatorüberladungen in diesem Beispiel, aber das würde zu vielen ähnlichen Überladungen führen).
Gibt es dafür eine Richtlinie?
Geben Sie so wenig implizite Conversions wie möglich an, da sie Probleme möglicherweise verbergen. Implizite Umwandlung reduziert die Explizitheit um den gleichen Betrag, um den sie die Kürze erhöhen. Manchmal ist das gut, aber manchmal nicht.
Ich finde es am besten, implizite Konvertierungen auf sehr ähnliche Typen zu beschränken, wie die nummerähnlichen Objekte in meinem obigen Beispiel: ein int
im Wesentlichen ist-a Complex
(von einem mathematischen Standpunkt, auch wenn es nicht über Vererbung modelliert wird, daher ist eine implizite Umwandlung sinnvoll.
In VB wird eine implizite Umwandlung " Widening
" genannt (im Gegensatz zu Narrowing
, das ist explicit
) und dies beschreibt es gut: keine Informationen gehen im Verlauf der Konvertierung verloren.
Außerdem ist ein Operator im Wesentlichen eine Builder-Funktion und hat (einige) die üblichen Vorteile einer Builder-Funktion gegenüber einem Konstruktor: Er kann nämlich zwischengespeicherte Werte wiederverwenden, anstatt immer neue Instanzen zu erstellen.
Betrachte mein Complex
Beispiel. Wir möchten möglicherweise Werte für häufig verwendete komplexe Zahlen zwischenspeichern:
Natürlich ist eine andere Frage, ob diese Mikrooptimierung effektiv ist.
Einer der Gründe für die Verwendung der impliziten Konvertierung mit so einfachen Typen wie XName ist, glaube ich, Bequemlichkeit beim Aufruf von Methoden.
Zum Beispiel können Sie
schreiben %Vor%Einfachheit beim Extrahieren von Daten ist das, worum es bei LINQ geht, und wenn wir schreiben mussten
%Vor%wäre LINQ auch für einfachste Abfragen für komplexe Abfragen total wert?
Ein weiteres wichtiges Thema ist, dass XNames atomisiert sind. Siehe MSDN :
XName-Objekte werden garantiert atomisiert; das heißt, Wenn zwei XName-Objekte genau denselben Namespace und denselben lokalen Namen haben, teilen sie dieselbe Instanz . Die Gleichheits- und Vergleichsoperatoren werden auch explizit für diesen Zweck zur Verfügung gestellt.
Diese Funktion ermöglicht unter anderem eine schnellere Ausführung von Abfragen. Beim Filtern nach dem Namen von Elementen oder Attributen verwenden die Vergleiche, die in Prädikaten ausgedrückt werden, einen Identitätsvergleich, keinen Wertvergleich. Es ist viel schneller festzustellen, dass zwei Referenzen sich tatsächlich auf dasselbe Objekt beziehen, als zwei Strings zu vergleichen.
Sie können keine Atomisierung im Konstruktor angeben, aber das Definieren einer Konvertierung ermöglicht es Ihnen, das entsprechende Objekt aus dem Pool auszuwählen und als eine neue Instanz zurückzugeben.
Die Verwendung von impliziten / expliziten Conversions ist ein Problem der Bequemlichkeit, und viele Programmierrichtlinien schlagen vor, dies zugunsten expliziter ConvertToXXX
-Methoden zu vermeiden.
Eines der Probleme ist, dass die Verwendung von impliziten / expliziten Konvertierungen Funktionen des Casting-Operators weiter überlastet. Es gibt ihm den doppelten Zweck von
Leider macht C # das schon in anderen Bereichen (mit Primitiven und Boxen).
Wenn zwei Klassen miteinander konvertierbar sein sollten, sie aber keine Schnittstelle einer Basisklasse teilen, die dieses Verhalten automatisch zulässt, würden Sie die Konvertierungen verwenden. Implizite Conversions sollten nie eine Möglichkeit des Datenverlusts haben; Sie werden oft als "erweiternde" Conversions angesehen. Wenn Sie beispielsweise int
in long
umwandeln, handelt es sich um eine Erweiterung der Konvertierung, und die Konvertierung ist implizit kein Problem. Explizite Konvertierungen können die Möglichkeit eines Datenverlusts beinhalten; a long
kann oder kann nicht in ein int
konvertiert werden, abhängig von seinem Wert.
Ein Trick, den ich bei impliziten Konvertierungen verwendet habe, ist das Konvertieren von Klassen in verschiedenen Namespaces, wenn ich keine andere vernünftige Option hatte. Ein WCF-Dienst gibt beispielsweise ein AuthenticationToken-Objekt zurück, das ich an einen WCF-Dienst in einem anderen Namespace übergeben muss. Beide haben dieses AuthenticationToken-Objekt, und eine konstante Konvertierung wäre ein Problem gewesen. Meine Lösung umfasste die Verwendung von public static implicit operator
in einer partiellen Klasse, um die Funktionalität für die Konvertierung in beide Richtungen hinzuzufügen.
Persönlich verwende ich die Konvertierungen, wenn ich weiß, dass die rhs in ein statisches Mitglied einer Klasse umgewandelt werden können (wie color = "red"
zu implizieren color = Colors.Red
sagen)
Ich verwende den neuen Operator, wenn ich tatsächlich eine neue Instanz erstellen möchte.
Tags und Links .net c# constructor type-conversion bcl