impliziter Operator auf generischen Typen
-
26-09-2019 - |
Frage
Gibt es etwas falsch mit einem impliziten Operator wie die folgenden verwenden:
//linqpad c# program example
void Main()
{
var testObject = new MyClass<int>() { Value = 1 };
var add = 10 + testObject; //implicit conversion to int here
add.Dump(); // 11
}
class MyClass<T>
{
public T Value { get; set; }
public static implicit operator T (MyClass<T> myClassToConvert)
{
return myClassToConvert.Value;
}
}
Ich dachte, ich als Instanz des Objekts als Wert gibt auf diese Weise behandeln könnte, aber da ich noch nie ein Beispiel dafür gesehen, ich dachte, vielleicht war es ein Grund nicht zu tun so etwas wie dies, dass jemand könnte darauf hinweisen?
In meinem eigentlichen Code Ich dachte an diese einer Datenabstraktionsschicht als Teil tun, damit ich Objekte mit Informationen zurückkehren konnte die zugrundeliegenden Daten beschreiben, sondern ermöglichen es dem Codelogik als Wert Art zu behandeln, wenn er braucht etwa ist der Wert, und zugleich zu wissen, halten sie alle nett und Art sicher mit den Generika.
Lösung
Wenn alle folgenden Bedingungen erfüllt sind:
-
alle mögliche Werte Ihres
MyClass<T>
-Typs (einschließlichnull
, wenn es nicht ein Werttyp ist!) Karte auf einen gültigen Wert vonT
-
der implizite Operator nie wirft (auch nicht für
null
!) -
die implizite Konvertierung macht semantischen Sinn und verwirrend ist nicht an den Client-Programmierer
, dann gibt es nichts falsch mit diesem. Natürlich können Sie könnte tun jeder dieser drei Dinge, aber es wäre schlechtes Design sein. Insbesondere ein impliziter Operator, weil der Ort zu debuggen wirft kann sehr hart sein, wo es genannt wird, sagt nicht, dass es aufgerufen wird.
Betrachten wir zum Beispiel, dass T?
keine implizite Konvertierung in T
hat (wo T
ist, natürlich, ein Werttyp). Wenn es eine solche implizite Operator war, wäre es zu werfen, wenn die T?
null ist, da es keine offensichtlichen Wert zu konvertieren null
ist, dass Sinn machen würde, für jeder Werttyp T
.
Lassen Sie mich ein Beispiel geben, wo ich Schwierigkeiten hatte, das Debuggen ein Problem, wo die implizite Operator warf:
public string Foo()
{
return some_condition ? GetSomething() : null;
}
Hier kehrte GetSomething
etwas von einer Art, ich schrieb, die eine benutzerdefinierte implizite Konvertierung in string
hat. Ich habe absolut sicher , dass GetSomething
konnte nie null
zurückkehren, und doch ich eine NullReferenceException
bekam! Warum? Da der obige Code ist nicht entspricht
return some_condition ? (string)GetSomething() : (string)null;
, sondern
return (string)(some_condition ? GetSomething() : (Something)null);
Jetzt können Sie sehen, wo der null
kam!
Andere Tipps
Das ist ein großes Muster. Denken Sie daran, um es als eine Variable vom Typ T
zu verwenden, müssen Sie entweder warfen es explizit auf T
, oder es auf eine Variable vom Typ T
zuweisen, dass. Die Besetzung findet automatisch in Methodenaufrufe und andere Dinge (wie Ihr Zusatz Beispiel), die eine T
nehmen.