Advanced Services | struct |
Ein struct ist ein Datenverbund. Sein Aufbau ist dem einer Klasse sehr ähnlich, es gibt einen Datenteil und es kann
Konstruktoren, Methoden und Properties geben. Es gibt allerdings auch deutliche Unterschiede. Am wichtigsten zunächst:
structs sind Werttypen, somit also keine Referenztypen und verhalten sich dementsprechend anders. Des weiteren
werden structs automatisch von System.ValueType abgeleitet (siehe Graphik) und können somit von keiner anderen
Klasse erben. Jedoch können structs beliebige Interfaces implementieren. Zudem sind structs "sealed", also
versiegelt, was heißt, daß weder ein struct noch eine Klasse ein von einem struct erben kann.
Es ist durchaus üblich, den Datenteil eines structs public zu machen. Da der Schutzzustand des Datenteils die
Eigenschaften eines structs beeinflußt unterscheiden wir hier structs nach dem Schutzzustand des Datenteils.
Wir betrachten die folgende struct-Definition:
struct Point1 { public int x; public int y; public override string ToString() { return "(" + x + "," + y + ")"; } }
Da der Datenteil public ist, brauchen wir weder Konstruktoren noch Properties bzw. setter/getter zu schreiben. Wir überschreiben lediglich die ToString()-Methode um eine bequeme Ausgabe der Daten mit Writeline() zu erreichen. Ein kleines Beispielprogramm kann folgendermaßen aussehen:
public static void Main(string[] args) { Point1 p1; p1.x = 27; p1.y = 28; Console.WriteLine(p1); }
Wird der Datenteil vor der Initialisierung verwendet, so meldet sich der Compiler mit der Fehlermeldung "use of unassigned local variable".
Erweitern Sie das obige Beispielprogramm und bestätigen Sie die folgenden Eigenschaften: Es gibt einen parameterlosen Konstruktor, der die Variablen des Datenteils mit 0 initialisiert. Seine Verwendung ist in diesem Fall optional. Weitere Konstruktoren können geschrieben werden, ebenso Properties und Methoden(was bei öffentlichem Datenteil aber nicht notwendig ist). Zeigen Sie, daß Properties und/oder Methoden erste dann verwendet werden können, wenn der Datenteil initialisiert ist. Stellen Sie fest, was passiert, wenn Sie den parameterlosen Konstruktor selbst schreiben wollen. Stellen Sie fest, was geschieht, wenn Sie den Datenteil direkt initialsieren möchten.
Ist der Datenteil private, so braucht man Konstruktoren, bzw. Properties, bzw. Methoden um den Datenteil zu initialisiern oder zu ändern. Macht man im obigen Beispiel den Datenteil privat, so kann man feststellen, daß es auch hier einen parameterlosen Konstruktor gibt, der den Datenteil mit 0 vorbelegt. Wir betrachten nun die folgende struct-Definition:
struct Point2 { private int x; private int y; public int X { get { return x; } set { x = value; } } public int Y { get { return y; } set { y = value; } } public override string ToString() { return "(" + x + "," + y + ")"; } }
Ein kleines Testprogramm kann so aussehen:
public static void Main(string[] args) { Point2 p2 = new Point2(); Console.WriteLine(p2); p2.X = 27; p2.Y = 28; Console.WriteLine(p2); }
Offensichtlich hat der Compiler einen parameterlosen Konstruktor erzeugt, der den Datenteil initialisiert.
Ersetzen Sie im obigen Beispielprogramm die properties durch set- und get-Methoden. Schreiben Sie einen Konstruktor dem man zwei Variablen vom Typ int übergeben kann und der den Datenteil entsprechend setzt. Wird in diesem Fall der parameterloser Konstruktor noch vom Compiler erzeugt ?
Die folgende Zusammenfassung gilt für alles structs, egal welchen Schutzzustand der Datenteil besitzt.
Legen Sie ein folgende struct-Typen an und untersuchen Sie ihr Verhalten
struct Dimension { public int[] dim; public string name; //etc. }
struct Dimension { private int[] dim; private name; public Dimension(int w, int h, String name) { // ... } //etc. }