Galileo Computing <openbook>
Galileo Computing - Programming the Net
Galileo Computing - Programming the Net


C# von Eric Gunnerson
Die neue Sprache für Microsofts .NET-Plattform
C# - Zum Katalog
gp Kapitel 10 Strukturen (Wertetypen)
  gp 10.1 Eine Point-Struktur
  gp 10.2 Boxing und Unboxing
  gp 10.3 Strukturen und Erstellungsroutinen
  gp 10.4 Entwurfsrichtlinien

Kapitel 10 Strukturen (Wertetypen)

Die meisten Objekte werden anhand von Klassen implementiert. Gelegentlich ist es jedoch wünschenswert, ein Objekt zu erstellen, das sich wie ein integrierter Typ verhält; ein Typ, der ohne viele Ressourcen auskommt, schnell zugeordnet werden kann und nicht den Overhead von Verweisen erzeugt. In diesem Fall wird ein Wertetyp verwendet, in C# durch das Deklarieren von struct.

Strukturen (struct-Elemente) verhalten sich ähnlich wie Klassen, weisen jedoch einige Einschränkungen auf. Sie können weder von anderen Typen erben (obwohl sie implizit von object erben) noch können andere Klassen von ihnen erben.


Galileo Computing

10.1 Eine Point-Struktur  downtop

In einem Grafiksystem kann eine Werteklasse zur Kapselung eines Punktes eingesetzt werden. Hier die zugehörige Deklaration:

using System;
struct Point
{
    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
    public override string ToString()
    {
        return(String.Format("({0}, {1})", x, y));
    }

    public int x;
    public int y;
}
class Test
{
    public static void Main()
    {
        Point    start = new Point(5, 5);
        Console.WriteLine("Start: {0}", start);
    }
}

Auf die x- und y-Komponenten von Point kann zugegriffen werden. In der Main()-Funktion wird Point mit Hilfe des Schlüsselwortes new erstellt. Bei den Wertetypen wird über new ein Objekt im Stack erstellt, anschließend wird die geeignete Erstellungsroutine aufgerufen.

Der Aufruf von Console.WriteLine() ist etwas undurchsichtig. Wenn Point dem Stack zugeordnet ist, wie funktioniert dann der Aufruf?


Galileo Computing

10.2 Boxing und Unboxing  downtop

In C# und der .NET-Laufzeitumgebung gibt es einen kleinen Zaubertrick, mit dem Wertetypen wie Verweistypen aussehen. Dieser kleine Zaubertrick heißt Boxing. Wie jeder Zaubertrick ist auch dieser sehr einfach. Beim Aufruf von Console.WriteLine() sucht der Compiler nach einer Methode, start in ein object zu konvertieren, da der Typ des zweiten Parameters zu WriteLine() object lautet. Für einen Verweistyp (z. B. eine Klasse) ist dies einfach, da object die Basisklasse aller Klassen darstellt. Der Compiler übergibt lediglich einen Verweis auf object, der auf die Klasseninstanz verweist.

Für eine Werteklasse hingegen ist keine verweisbasierte Instanz vorhanden, daher weist der C#-Compiler Point einen Verweis vom Typ box zu, kennzeichnet, dass die Box einen Punkt (Point) enthält und kopiert den Wert von Point in die Box. Jetzt handelt es sich um einen Verweistyp, der wie ein object behandelt werden kann.

Dieser Verweis wird anschließend an die Funktion WriteLine() übergeben, die die Funktion ToString() für denjenigen Point aufruft, für den das Boxing durchgeführt wurde. Dieser wiederum wird an die ToString()-Funktion übermittelt, und es wird folgender Code erzeugt:

Start: (5, 5)

Das Boxing findet automatisch immer dort statt, wo ein Wertetyp verwendet wird, jedoch ein object erforderlich ist (oder verwendet werden könnte).

Der nach dem Boxing erhaltene Wert wird durch ein Unboxing wieder als Wertetyp abgerufen:

int v = 123;
object o = v;        // Boxing in int 123
int v2 = (int) o;    // Unboxing in einen integer-Wert

Durch Zuweisung des Wertes 123 zum Objekt o findet ein Boxing in integer statt. In der nächsten Zeile wird der Wert wieder umgewandelt. Die Typumwandlung in int ist erforderlich, da das Objekt o von beliebigem Typ sein und die Typumwandlung fehlschlagen könnte.

Dieser Code kann durch Abbildung 10.1 grafisch dargestellt werden. Die Zuordnung von int zur object-Variablen führt dazu, dass die Box dem Heap zugeordnet und der Wert in die Box kopiert wird. Die Box wird anschließend mit dem Typ gekennzeichnet, den sie enthält, damit zur Laufzeit der Objekttyp bekannt ist, für den das Boxing durchgeführt wurde.

Abbildung 10.1  Boxing und Unboxing für einen Wertetyp
Abbildung

Während des Unboxings muss der Typ exakt übereinstimmen, denn es ist keine Rückkonvertierung in einen kompatiblen Typ möglich:

object o = 15;
short s = (short) o;        // Schlägt fehl, o enthält keinen 
short-Wert
short t = (short)(int) o;    // Diese Variante funktioniert

Galileo Computing

10.3 Strukturen und Erstellungsroutinen  downtop

Strukturen und Erstellungsroutinen verhalten sich etwas anders als Klassen. Bei Klassen muss eine Instanz durch das Aufrufen von new vor der Objektverwendung erstellt werden. Wenn new nicht aufgerufen wird, wird keine Instanz erstellt, und der Verweis ist null.

Mit einer Struktur ist jedoch kein Verweis verknüpft. Wenn new nicht für struct aufgerufen wird, wird eine Instanz erstellt, deren sämtliche Felder Nullen enthalten. In einigen Fällen kann ein Benutzer die Instanz dann ohne weitere Initialisierung verwenden. Es muss daher sichergestellt werden, dass sämtliche Nullstatuswerte einen gültigen Initialisierungsstatus für alle Wertetypen darstellen.

Eine Standarderstellungsroutine (ohne Parameter) für eine Struktur könnte andere Werte setzen als der Nullstatus, was wiederum zu einem unerwarteten Verhalten führen kann. Die .NET-Laufzeitumgebung verbietet daher Standarderstellungsroutinen für Strukturen.


Galileo Computing

10.4 Entwurfsrichtlinien  toptop

Strukturen sollten lediglich für Typen eingesetzt werden, bei denen es sich nur um kleine Dateneinheiten handelt – für Datentypen, die in ähnlicher Weise verwendet werden können wie die integrierten Datentypen. Beispielsweise für den integrierten Typ decimal, der als Wertetyp implementiert ist.

Selbst wenn komplexere Datentypen als Wertetypen implementiert werden können, sollte dies eher vermieden werden, da die bei Wertetypen verwendete Logik vom Benutzer höchstwahrscheinlich nicht erwartet wird. Der Benutzer wird so beispielsweise erwarten, dass eine Variable den Typ null aufweisen kann, was bei Wertetypen allerdings nicht möglich ist.

   

Einstieg in Visual C# 2005

Visual C#

Einstieg in Visual Basic .NET 2005

Visual Basic .NET 2005






Copyright © Galileo Press GmbH 2001 - 2002
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, fon: 0228.42150.0, fax 0228.42150.77, info@galileo-press.de