9.6 Konvertierung von Generics
Die implizite Konvertierung eines generischen Typparameters ist nur statthaft, wenn der Zieldatentyp Object ist oder einer der Typen, die als Constraint hinter where angeführt sind.
class Demo<T> where T : DemoBase, IComparable {
public void DoSomething(T param) {
IComparable var1 = param;
DemoBase var2 = param;
Object var3 = param;
}
}
Listing 9.11 Konvertierung eines generischen Typparameters
Die Klasse Demo beschreibt den Typparameter T, der den folgenden Bedingungen genügen muss: Der konkrete Typ muss von der Klasse DemoBase abgeleitet sein und das Interface IComparable implementieren. Die Zuweisungen in DoSomething sind damit gültig und typsicher.
An Demo wollen wir nun noch eine Manipulation vornehmen, indem wir auf die Constraints verzichten. Wir haben dann immer noch die Möglichkeit, implizit in Object zu konvertieren. Die Konvertierung in eine Schnittstelle muss explizit erfolgen. Weil der Compiler zur Kompilierzeit nicht weiß, durch welchen konkreten Typ der Typparameter zur Laufzeit ersetzt wird, wird er diese Konvertierung akzeptieren. Nicht erlaubt ist hingegen die explizite Konvertierung in irgendeine Klasse.
class Demo<T> {
public void DoSomething(T param) {
// korrekt !!!
IComparable var1 = (IComparable)param;
// fehlerhaft !!!
DemoBase var2 = (DemoBase)param;
Object var3 = param;
}
}
Listing 9.12 Typkonvertierung eines allgemeinen generischen Typparameters
Obwohl der Compiler die explizite Konvertierung in eine Schnittstelle akzeptiert, bleibt festzustellen, dass diese Operation nicht ganz ungefährlich ist und zur Laufzeit eine Ausnahme verursachen kann, wenn der generische Typ die Schnittstelle nicht implementiert. Um dieser potenziellen Gefahr aus dem Weg zu gehen, bietet sich eine Alternative mit den Operatoren is bzw. as an. Zur Erinnerung: Mit beiden Operatoren lässt sich der Typ einer Referenz überprüfen. is liefert true zurück, wenn der linke Operand vom Typ des rechten ist. Der as-Operator führt in diesem Fall sogar eine Konvertierung durch, andernfalls ist der Rückgabewert null.
Das folgende Listing zeigt, wie Sie die genannten Operatoren zur Typüberprüfung einsetzen können.
class Demo<T> {
public void DoSomething(T param) {
if (param is IComparable) {...}
// oder alternativ:
if (param as IComparable!= null) {...}
}
}
Listing 9.13 Konvertierung eines generischen Typparameters mit »is« oder »as«
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.