Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs

Sichere Konvertierungen von Referenztypen

Geschrieben von: Christoph Wille
Kategorie: C#

This printed page brought to you by AlphaSierraPapa

Ein Thema, das sich immer wieder als problematisch für Einsteiger herausstellt, ist das Konvertieren ("Casten") von Referenztypen (aka Objekten). Unter C++ konnte man damit sehr viel Unheil anstellen, was einem zum Glück mit C# nicht passieren kann. Trotz oder gerade wegen der Typsicherheit der Sprache sollte man sich mit den verschiedenen Techniken vertraut machen:

Um das Ganze anschaulich zu präsentieren, habe ich ein nettes Szenario gewählt: wir versuchen Äpfel in Orangen umzuwandeln - etwas, das C# nicht zulassen wird (also gut geeignet ist zu zeigen, wie man mit Konvertierungsfehlern umgehen muß). Der Ausgangssourcecode aller Samples ist der folgende (classes.aspx):

<script language=c# runat=server>
class apple
{
  public string Fruit() { return "Apple"; }
}

class orange
{
  public string Fruit() { return "Orange"; }
}
</script>
<% @page language=c# %>
<%
 apple myApple = new apple();
 orange myOrange = new orange();
 Response.Write(myApple.Fruit()+"<br>");
 Response.Write(myOrange.Fruit()+"<br>");
%>

Casten

Obwohl wir daran scheitern werden, versuchen wir es anfangs mal mit dem Kopf durch die Wand:

 apple myApple = new apple();
 orange anotherOrange = (orange)myApple;

An diesem Code hat bereits der Compiler etwas auszusetzen: er weiß, daß diese Konvertierung nicht gültig ist, und kompiliert den Code erst gar nicht. Der Grund ist klar, weil die apple Klasse mit orange Klasse nichts gemeinsam hat.

Also wählen wir einen anderen Weg, einen, den man im echten Leben oft sieht - zuerst wird ein Typ in eine generelle object Variable gepfercht (zB wenn man Elemente in Stacks, Queues oder ArrayLists speichert), und später zu Wiederverwendungszwecken in den (vermeintlich) richtigen Typ zurückkonvertiert:

 apple myApple = new apple();
 // folgende Zeile steht für potentiell kompliziertere Operationen
 object objGeneral = myApple;
 orange anotherOrange = (orange)objGeneral;

Wenn man so wie wir hier den falschen Typ wählt, bekommt man bei C# einen auf die Finger - nämlich eine InvalidCastException zur Laufzeit. Um diesen Fehler korrekt abzufangen, benötigt man Exception Handling Code, zB:

 apple myApple = new apple();
 object objGeneral = myApple;
 try
 {
   orange anotherOrange = (orange)objGeneral;
   // do whatever you want with the orange
 }
 catch(InvalidCastException e)
 {
   // either do nothing or tell the user
 }

Obwohl jetzt alle Fehler behandelt werden, finde ich über den Fehlschlag des Casts erst durch eine Exception heraus. Es wäre doch deutlich besser und intelligenter, vorher fragen zu können, ob ein Cast gutgehen kann oder nicht. Und hier kommt der is Operator ins Spiel.

Der is Operator

Wie bereits angekündigt, der is Operator erlaubt es, abzufragen ob ein Cast gutgeht, oder eine Exception liefern wird. Das folgende Sourcecodesnippet zeigt, wie man den is Operator in einer Applikation einsetzen kann:

 apple myApple = new apple();
 object objGeneral = myApple;
 
 if (objGeneral is orange)
 {
   orange anotherOrange = (orange)objGeneral;
   // do whatever you want with the orange
 }
 else
 {
   Response.Write("this is no orange");
 }

Ich möchte nur noch einen Hinweis zwecks des is Operators loswerden - steht zur Compilezeit bereits fest, daß der Cast immer gutgehen bzw immer fehlschlagen würde, gibt es eine Compilerwarnung - die man in ASP.NET allerdings leider nicht zu Gesicht bekommt.

Der as Operator

Den as Operator könnte man als Exception-less Cast bezeichnen. Die Konvertierung wird still durchgeführt - geht die Konvertierung schief, hat die Zielvariable der Konvertierung den Wert null. Alles, was man zu tun hat, ist diese Variable dann in einer if-Abfrage zu kontrollieren:

 apple myApple = new apple();
 object objGeneral = myApple;
 
 orange anotherOrange;
 anotherOrange = objGeneral as orange;
 if (null != anotherOrange)
 {
   // do whatever you want with the orange
 }
 else
 {
   Response.Write("this is no orange");
 }

Für den as Operator gilt übrigens das Gleiche, wie für den is Operator - man bekommt eine Warnung, wenn der Cast immer gutgehen oder fehlschlagen würde, wie zB in diesem Code:

apple myApple = new apple;
apple anotherApple = myApple as apple;

Schlußbemerkung

Es führen immer viele Wege nach Rom, allerdings sind einige steiniger als andere. Mein persönlicher Favorit für Typkonvertierungen ist der is Operator.

This printed page brought to you by AlphaSierraPapa

Download des Codes

Klicken Sie hier, um den Download zu starten.
http://www.aspheute.com/code/20001019.zip

Verwandte Artikel

Das using Schlüsselwort
http:/www.aspheute.com/artikel/20020318.htm
Einführung: C#-Klassen in ASP.NET
http:/www.aspheute.com/artikel/20001012.htm
Exception Handling in C#
http:/www.aspheute.com/artikel/20000724.htm
Formularbasierte Authentifizierung in fünf Minuten
http:/www.aspheute.com/artikel/20020705.htm
Unions in C#
http:/www.aspheute.com/artikel/20020207.htm
Variable Parameterlisten in Funktionen
http:/www.aspheute.com/artikel/20020125.htm

 

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.