In C # können wir den impliziten Konvertierungsoperator wie folgt überladen (Beispiel von MSDN ):
struct Digit
{
/* ... */
public static implicit operator byte(Digit d) // implicit digit to byte conversion operator
{
/* ... */
}
}
So können wir einen Typ haben, eine Art benutzerdefinierten Wert , auf magische Weise selbst zu einem anderen (nicht verwandten) Typ konvertieren, das Publikum fassungslos verlassen (bis sie in den hinter den Kulissen und sehen Sie die implizite Konvertierung Operator Peer, das ist).
Ich lasse nicht gerne jemanden, der meinen Code verwirrt liest. Ich glaube nicht, dass es viele Leute tun.
Die Frage ist, welche Anwendungsfälle der implizite Typkonvertierungsoperator bietet, der das Verständnis meines Codes nicht wesentlich erschwert.
Antworten:
Ich würde nur implizite Konvertierungen zwischen Typen empfehlen, die ungefähr dieselben Werte auf unterschiedliche Weise darstellen. Zum Beispiel:
RGB
,HSL
,HSV
undCMYK
.Meter
vsInch
).Es gibt jedoch einige strenge Richtlinien, die angeben, wann es nicht angemessen ist, eine implizite Konvertierung zu definieren:
InvalidCast
) - Ausnahme auslösen kann, sollte sie nicht implizit sein.O(1)
Operation ist, sollte sie nicht implizit sein.Angenommen, Ihr Conversion-Operator
f: T1 -> T2
verstößt nicht gegen eine der oben genannten Regeln, dann weist das folgende Verhalten nachdrücklich darauf hin, dass die Conversion implizit sein kann:a == b
dannf(a) == f(b)
.a != b
dannf(a) != f(b)
.a.ToString() == b.ToString()
dannf(a).ToString() == f(b).ToString()
.T1
undT2
.quelle
T1
(impliziert durch die==
Beziehung vonT1
) immer zwei Werten innerhalb derselben Äquivalenzklasse von zugeordnet sindT2
. Nun, da ich darüber nachdenke, denke ich, dass die erste Eigenschaft für eine implizite Konvertierung tatsächlich erforderlich sein sollte.Wenn die Typen nicht unabhängig sind (für Programmierer). Es gibt (seltene) Szenarien, in denen Sie zwei nicht verwandte Typen haben (was den Code betrifft), die tatsächlich verwandt sind (was die Domäne oder vernünftige Programmierer betrifft).
Zum Beispiel Code für den String-Abgleich. Ein häufiges Szenario besteht darin, ein Zeichenfolgenliteral abzugleichen. Anstatt anzurufen
IsMatch(input, new Literal("some string"))
, können Sie bei einer impliziten Konvertierung diese Zeremonie - das Rauschen im Code - loswerden und sich auf das Zeichenfolgenliteral konzentrieren.Die meisten Programmierer werden
IsMatch(input, "some string")
schnell erkennen und verstehen, was gerade vor sich geht. Dadurch wird Ihr Code auf der Anrufseite klarer. Kurz gesagt, es macht es etwas einfacher zu verstehen , was los ist, in einem geringen Aufwand an , wie das vor sich geht.Nun könnten Sie argumentieren, dass eine einfache Funktionsüberladung, um dasselbe zu tun, besser wäre. Und es ist. Aber wenn so etwas allgegenwärtig ist, ist eine einzige Konvertierung sauberer (weniger Code, höhere Konsistenz) als ein Haufen Funktionsüberladungen.
Und Sie könnten argumentieren, dass es besser ist, Programmierer zu verpflichten, den Zwischentyp explizit zu erstellen, damit sie sehen, "was wirklich los ist". Das ist weniger einfach. Persönlich denke ich, dass das wörtliche String-Match-Beispiel sehr deutlich macht, was wirklich vor sich geht - der Programmierer muss nicht wissen, wie alles abläuft. Wissen Sie, wie der gesamte Code von den verschiedenen Prozessoren ausgeführt wird, auf denen der Code ausgeführt wird? Es gibt immer eine Linie der Abstraktion , wo Programmierer fürsorglich aufhören , darüber , wie etwas funktioniert. Wenn Sie der Meinung sind, dass die impliziten Konvertierungsschritte wichtig sind, verwenden Sie die implizite Konvertierung nicht. Wenn Sie denken, sie sind nur eine Zeremonie, um den Computer bei Laune zu halten, und der Programmierer wäre besser dran, wenn er dieses Geräusch nicht überall sehen würde,
quelle