Konvertierung und Boxing

Aus Das Sopra Wiki
Wechseln zu: Navigation, Suche

Implizite und explizite Konvertierung

Da es sich bei C# um eine typsichere Sprache handelt, kann jede Variable, die einen bestimmten Datentyp hat, auch nur die Werte enthalten, die diesem Datentyp entsprechen. Allerdings kann dies nicht immer vorausgesetzt werden. Aus diesem Grund gibt es die möglichkeit, verschiedene Konvertierungen von Datentypen vorzunehmen, nämlich

  • Implizite Konvertierung und
  • explizite Konvertierung (casting).

Wird eine implizite Konvertierung vorgenommen, bekommt der Programmierer davon meist nichts mit. Diese wird vom Compiler erledigt. Datentypen, die ohne Wert- oder Genauigkeitsverlust in einen anderen Typen umgewandelt werden können, werden implizit konvertiert. Beispielsweise kann ein Wert vom Typ int ohne Probleme in einen Wert vom Typ long konvertiert werden.

Wenn allerdings Verluste auftreten können, weigert sich der Compiler, eine Konvertierung vorzunehmen. Eine Konvertierung kann jedoch explizit erzwungen werden. Dies Geschieht mit Hilfe des sogenannten Casts. Dabei wird der neue Typ, in den konvertiert werden soll, vor den zu konvertierenden Wert oder die zu konvertierende Variable in Klammern geschrieben. Dies ist auch mit Zeichen und ihrer Repräsentation als Zahlenfolge möglich:

short s = 0;
int   i = 10;

s = i;        // Fehler: Der Wertebereich von i ist größer als der von s
s = (short)i; // OK: Explizite Konvertierung (cast) von int zu short

char c = (char)65;    // Konvertiert den Zahlenwert 65 in 'A'
int  z = (int)'A';    // Konvertiert 'A' in den Zahlenwert 65

Boxing und Unboxing

Obwohl sich in C# Werte- und Referenztypen unterschiedlich verhalten, sind sie innerhalb des .NET-Frameworks wie alles andere auch aus Klassen (bzw. Strukturen) implementiert. Wertetypen stammen von der Klasse ValueType ab, die wiederum von der Klasse Object abgeleitet ist. Da sich in .NET alles von Object ableitet, ist der Datentyp object quasi ein Platzhalter für jeden beliebigen anderen Datentyp.

Es gibt viele Methoden, die als Übergabeparameter Werte vom Typ Object erwarten. Diese Methoden werden auch als universelle Methoden bezeichnet, da sie mit jedem Datentyp umgehen können. Wenn einer solchen Methode ein Wert übergeben wird, wird dieser in einem Objekt "verpackt". Das Objekt dient sozusagen als "Hülle" um einen Datentyp, der eigentlich ein Wertetyp ist. Diese Art, einen Wertetyp zu verpacken, ihn also in eine "Box" zu stecken, bezeichnet man als Boxing.

Beim Boxing handelt es sich um eine implizite Konvertierung. Diese wird vom Compiler erledigt und braucht kein Zutun des Programmierers. Soll allerdings der "verpackte" Wert wieder entnommen werden, muss eine explizite Rückkonvertierung durchgeführt werden. Diese Rückkonvertierung bezeichnet man als Unboxing:

int i = 100;
object o = i;                    // Boxing
int u = (int)o;                  // Unboxing

Console.WriteLine(o.GetType());  // Ausgabe: System.Int32

Boxing und Unboxing sollte jedoch immer im Zusammenhang mit der Ausführungsgeschwindigkeit gesehen werden. Sowohl Boxing als auch Unboxing sind relativ rechenintensive Prozesse. Beim Boxing wird ein komplett neues Objekt erzeugt, das heißt, der Speicher muss reserviert und das neue Objekt muss instantiiert werden. Dieser Prozess kann bis zu 20 mal länger dauern, als eine gewöhnliche Wertezuweisung. Beim Unboxing kann der Prozess des Castens bis zu vier mal so lange dauern, wie eine Wertezuweisung. Aus diesem Grund sollte besonders bei performanztechnischen Aspekten sehr darauf geachtet werden, an welcher Stelle Boxing und Unboxing sinnvoll ist und verwendet werden kann.[1]

Andere Konvertierungsmethoden

.NET bietet neben den oben genannten Konvertierungsmöglichkeiten auch etliche andere Möglichkeiten, wie ein Wert in einen anderen Konvertiert werden kann. Die vermutlich meist benutzt Konvertierung ist die von einer Zahl in einen String und umgekehrt. Diese wird hier kurz behandelt, um das .NET-Paradigma der sonstigen Konvertierungen zu zeigen.

Um einen beliebigen Datentyp, also auch eine Ganzzahl, in einen String umzuwandeln, steht jedem Objekt die Methode ToString() zur Verfügung. Im Prinzip kann mit dieser Methode jedes Objekt und jeder Typ in einen String umgeandelt werden. Allerdings muss die Umwandlungsoperation manchmal von Hand programmiert werden, damit die Umwandlung in die gewünschte Ausgabe funktioniert.

Um eine Zahl in einen String umzuwandeln reicht es, wenn hinter den Bezeichner einer Zahl einfach der Aufruf von ToString() folgt. Für die Rückrichtung muss eine Parsing-Methode aufgerufen werden, da es auch Zeichenketten geben kann, in denen nicht nur Zahlen, sondern auch Buchstaben vorkommen. Die Parsing-Methode überprüft dabei, ob in der Zeichenkette eine Zahl vorhanden ist und wandelt diese in eine Zahl zurück.

int i = 15;
string s = i.ToString();            // Speichert in s den Wert "15"
int z = Int.Parse(s);               // Wandelt "15" zurück in 15 und speichert den Wert in z
In C# existieren noch viele weitere dieser Parsing-Funktionen.