Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort zur 5. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Klassendesign
4 Vererbung, Polymorphie und Interfaces
5 Delegates und Ereignisse
6 Weitere .NET-Datentypen
7 Weitere Möglichkeiten von C#
8 Auflistungsklassen (Collections)
9 Fehlerbehandlung und Debugging
10 LINQ to Objects
11 Multithreading und die Task Parallel Library (TPL)
12 Arbeiten mit Dateien und Streams
13 Binäre Serialisierung
14 Einige wichtige .NET-Klassen
15 Projektmanagement und Visual Studio 2010
16 XML
17 WPF – Die Grundlagen
18 WPF-Containerelemente
19 WPF-Steuerelemente
20 Konzepte der WPF
21 Datenbindung
22 2D-Grafik
23 ADO.NET – verbindungsorientierte Objekte
24 ADO.NET – Das Command-Objekt
25 ADO.NET – Der SqlDataAdapter
26 ADO.NET – Daten im lokalen Speicher
27 ADO.NET – Aktualisieren der Datenbank
28 Stark typisierte DataSets
29 LINQ to SQL
30 Weitergabe von Anwendungen
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual C# 2010 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2010

Visual C# 2010
geb., mit DVD
1295 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1552-7
Pfeil 6 Weitere .NET-Datentypen
Pfeil 6.1 Strukturen
Pfeil 6.1.1 Definition einer Struktur
Pfeil 6.1.2 Initialisieren einer Struktur
Pfeil 6.1.3 Weitere Merkmale einer Struktur
Pfeil 6.1.4 Verschachtelte Strukturen
Pfeil 6.1.5 Änderung im Projekt »GeometricObjects«
Pfeil 6.2 Enumerationen (Aufzählungen)
Pfeil 6.2.1 Wertzuweisung an »enum«-Mitglieder
Pfeil 6.2.2 Alle Mitglieder einer Aufzählung durchlaufen

6 Weitere .NET-Datentypen

Bisher haben wir Objekte erzeugt, indem wir eine Klasse instanziierten. Objekte beanspruchen aber Systemressourcen, denn mit jedem Objekt ist ein Verwaltungsoverhead verbunden. Bei einzelnen Objekten fällt das kaum ins Gewicht; ein Objekt-Array, das möglicherweise Tausende typgleicher Objekte enthält, kann die Systemleistung jedoch spürbar negativ beeinflussen.

Die .NET-Laufzeitumgebung stellt aus diesem Grund ein Konstrukt bereit, das sich ähnlich wie eine Klasse verhält, dabei jedoch die wertvollen Ressourcen schont: die Struktur. Strukturen werden von der Laufzeitumgebung als Wertetyp behandelt.

Anschließend werden wir uns noch einer zweiten Typdefinition widmen: der Konstantenaufzählung oder Enumeration.


Galileo Computing - Zum Seitenanfang

6.1 Strukturen Zur nächsten ÜberschriftZur vorigen Überschrift


Galileo Computing - Zum Seitenanfang

6.1.1 Definition einer Struktur Zur nächsten ÜberschriftZur vorigen Überschrift

Eine Struktur beschreibt einen Datentyp, der sich aus Elementen verschiedener Typen zusammensetzt, die miteinander in einer festen Beziehung stehen und eine in sich geschlossene Einheit bilden. Stellen Sie sich vor, Sie wollten ein Auto beschreiben, das durch einen Preis, eine Höchstgeschwindigkeit und einen Hubraum gekennzeichnet ist. Außerdem soll die Klasse die Methoden Fahren und Hupen veröffentlichen. Die Klassendefinition könnte folgendermaßen lauten:


public class Car {
  public decimal Preis; 
  public float Höchstgeschwindigkeit; 
  public float Hubraum;   
  public void Fahren() {
    // Anweisungen
  }   
  public void Hupen() {
    // Anweisungen
  } 
}

Tatsächlich unterscheidet sich die analoge Definition einer Struktur Car kaum von der einer Klasse – abgesehen vom Austausch des Schlüsselwortes class durch struct:


public struct Car {
  ...
}

Im ersten Moment mag das zu der Schlussfolgerung verleiten, man könne eine Klasse grundsätzlich durch eine Struktur ersetzen. Wie im weiteren Verlauf dieses Kapitels aber noch gezeigt werden wird, sind die Fähigkeiten einer Struktur im Vergleich zu denen einer Klasse eingeschränkt.

Dass die Aussage, eine Struktur sei ein Wertetyp, korrekt ist, wird schon bei der Deklaration einer Variablen deutlich. Würde Car als Klasse definiert, müsste vor dem ersten Aufruf eine Instanz durch das Aufrufen des Operators new erzeugt werden:


// Annahme: Car liegt als class-Definition vor
Car myCar = new Car();
myCar.Hubraum = 1900;

Eine Struktur wird demgegenüber von der Laufzeitumgebung jedoch wie die Variable eines elementaren Datentyps eingesetzt, da kein Verweis damit verknüpft ist:


// Car liegt als struct-Definition vor
Car myCar;

Der Zugriff auf die Elemente einer Struktur erfolgt ebenfalls mit dem Punktoperator, z. B. so:


myCar.Hubraum = 1900;


Galileo Computing - Zum Seitenanfang

6.1.2 Initialisieren einer Struktur Zur nächsten ÜberschriftZur vorigen Überschrift

Eine Struktur ist die Beschreibung eines Datentyps. Um das Objekt einer Struktur nutzen zu können, benötigt man eine Variable dieses Typs. Im folgenden Beispiel ist die Struktur Person mit den Feldern Name und Alter definiert. In der Main-Methode wird die Variable pers vom Typ Person deklariert und werden den Feldern Werte zugewiesen.


struct Person {
  public string Name;
  public int Alter;
}
class Program {
  static void Main(string[] args) {
    Person pers;
    pers.Name = "Willi Jakob";
    pers.Alter = 35;  
  }
}

Der Name (Willi Jakob) und das Alter (35) sind einem ganz bestimmten Element zugeordnet, nämlich pers. Das erinnert an die Instanzvariablen einer Klasse, die ebenfalls objektgebunden sind. Der Vergleich ist auch nicht falsch, denn eine Strukturvariable ist einem Objektverweis sehr ähnlich, was durch die zweite Variante, eine Variable vom Typ einer Struktur zu deklarieren, besonders deutlich wird:


Person pers = new Person();
pers.Alter = 35;  

Die Syntax ist dieselbe wie bei der Instanziierung einer Klasse und deutet bereits darauf hin, dass es innerhalb einer Struktur einen Konstruktor geben muss, der parameterlos ist. Mit new wird dieser Konstruktor aufgerufen, der – wie auch der Konstruktor einer Klasse – die Felder des Objekts initialisiert.

Wenn Sie ein Objekt vom Typ einer Struktur mit new deklarieren, sind alle Felder initialisiert und ermöglichen einen sofortigen Zugriff. Verzichten Sie auf den new-Operator, muss einem Feld zuerst ein Wert zugewiesen werden, bevor es ausgewertet werden kann. Aus diesem Grund lehnt der C#-Compiler die Kompilierung des folgenden Codefragments ab: In der vierten Anweisung wird versucht, den Inhalt des noch nicht initialisierten Feldes an der Konsole anzuzeigen.


Person pers1 = new Person();
Person pers2;
Console.Write(pers1.Name);
Console.Write(pers2.Name);


Galileo Computing - Zum Seitenanfang

6.1.3 Weitere Merkmale einer Struktur Zur nächsten ÜberschriftZur vorigen Überschrift

Klassen und Strukturen stellen in vielerlei Hinsicht dieselben Möglichkeiten zur Verfügung. Beispielsweise können in Strukturen Eigenschaften, Methoden und Ereignisse definiert sowie Schnittstellen implementiert werden. Die Methodenüberladung ist nach denselben Regeln wie in den Klassen erlaubt.

Es gibt jedoch auch einige Einschränkungen, die in Kauf genommen werden müssen, wenn Sie sich anstelle einer Klasse für eine Struktur entscheiden. Das wichtigste Unterscheidungsmerkmal ist, dass Strukturen weder Klassen noch andere Strukturen beerben können. Strukturen können auch nicht abgeleitet werden. Von dieser Regel gibt es nur eine Ausnahme: Implizit beerben Strukturen die Klasse ValueType, die ihrerseits eine direkte Subklasse von Object ist.

Standardmäßig stellt eine Struktur einen parameterlosen Konstruktor bereit, der mit


Person pers = new Person();

aufgerufen werden kann. Strukturen lassen die Definition weiterer Konstruktoren zu, die jedoch parametrisiert sein müssen, denn das Überschreiben des parameterlosen Konstruktors einer Struktur ist nicht erlaubt. Fügen Sie einen parametrisierten Konstruktor hinzu, müssen darin alle Felder der Struktur initialisiert werden, wie das folgende Beispiel zeigt:


struct Person {
  public string Name;
  public int Alter;
  // Konstruktor
  public Person(string name) {
    Alter = 0;
    Name = name;
  }
}

Der Aufruf eines parametrisierten Konstruktors führt nur über den new-Operator. Vorsicht ist hierbei geboten, denn das folgende Codefragment hat die doppelte Initialisierung der Variablen pers zur Folge, weil in der zweiten Anweisung ein parametrisierter Konstruktor aufgerufen wird:


Person pers;
pers = new Person("Willi", 13);

Läge Person eine Klasse zugrunde, würde es nur zu einem Konstruktoraufruf kommen.

Es gibt noch ein anderes Merkmal, durch das sich Strukturen von Klassen unterscheiden. Während die Initialisierung eines Feldes in einer Klasse anstandslos möglich ist, wird das vom C#-Compiler in einer Struktur abgelehnt. Die folgende Definition von Person ist deshalb auch falsch:


public struct Person {
  // die Initialisierung der Felder ist unzulässig
  public string Zuname = "";
  public int PersonalID = 0;
}

Richtig muss es lauten:


public struct Person {
  public string Zuname;
  public int PersonalID;
}


Galileo Computing - Zum Seitenanfang

6.1.4 Verschachtelte Strukturen Zur nächsten ÜberschriftZur vorigen Überschrift

Sollte es erforderlich sein, können Sie Stukturen ineinander verschachteln.


public struct Mitarbeiter {
  public struct Position {
    public string Bezeichnung;
    public double Gehalt;
  }
  public string Geschlecht;
  public int Alter;
  public Position Rang;
}

Die Struktur Position mit ihren öffentlichen Elementen Bezeichnung und Gehalt ist in die Struktur Mitarbeiter eingebettet, die ihrerseits selbst drei Elemente für den externen Zugriff bereitstellt. Das Element Rang ist vom Typ der eingebetteten Struktur. Der Zugriff auf die untergeordnete Ebene erfolgt mit der üblichen Punktnotation. Zuerst wird das äußere Element genannt, danach das direkt untergeordnete, zum Beispiel:


Mitarbeiter newPerson;
newPerson.Rang.Bezeichnung = "Boss";
newPerson.Rang.Gehalt = 20000; 


Galileo Computing - Zum Seitenanfang

6.1.5 Änderung im Projekt »GeometricObjects« topZur vorigen Überschrift

Wir wollen uns nun erneut der Anwendung GeometricObjectsSolution zuwenden. An einer Stelle bietet es sich an, eine Struktur einzusetzen: Es handelt sich dabei um die beiden Mittelpunktskoordinaten XKoordinate und YKoordinate, die in der Klasse GeometricObject definiert sind und nun durch die Struktur Point beschrieben werden sollen. Der Typ Point ist sehr einfach aufgebaut und hat nur die beiden Felder X und Y, die später den Mittelpunkt eines Kreisobjekts beschreiben sollen. Außerdem enthält die Struktur einen zweiparametrigen Konstruktor, dem beim Aufruf die Punktkoordinaten übergeben werden.


public struct Point {
  public int X;
  public int Y;
  public Point(int x, int y) {
    X = x;
    Y = y;
  }
}

In der Klasse GeometricObject zieht das selbstverständlich Änderungen nach sich. Wir definieren zuerst ein Feld vom Typ der Struktur. Dieses soll in der überarbeiteten Fassung die Werte des Bezugspunktes aufnehmen.


protected Point _Center = new Point();

Dabei sollte explizit der parameterlose Konstrukor aufgerufen werden, damit X und Y im Feld _Center von Anfang an initialisiert sind und einen definierten Anfangszustand haben.

Von der Einführung der Struktur Point sind auch die Konstruktoren von Circle und Rectangle betroffen, die die beiden Mittelpunktskoordinaten in ihren Parametern erwarten.


public Circle(double radius, int xPos, int yPos) : this(radius) {
  _Center.X = xPos;
  _Center.Y = yPos;
}
public Rectangle(double length, double width int xPos, int yPos,):this(length, width) {
  _Center.X = xPos;
  _Center.Y = yPos;
}

Bedingt durch die Änderung sollten wir nun auch zwei Eigenschaftsmethoden in GeometricObject definieren, um die X- und Y-Position der Objekte zu veröffentlichen.


public int XCoordinate {
  get {return _Center.X;}
  set {_Center.X = value;}
}         
public int YCoordinate {
  get {return _Center.Y;}
  set {_Center.Y = value;}
}

Eine gute Klassendefinition zeichnet sich nicht nur dadurch aus, dass sie die Implementierung auf das Notwendigste beschränkt, sondern deckt auch die Fälle ab, die für einen Benutzer unter Umständen sinnvoll sein könnten. Soll der Mittelpunkt eines Kreisobjekts diagonal verschoben werden, sind zwei Anweisungen notwendig. Vorteilhafter ist es, dasselbe mit einer Anweisung zu erreichen. Die Verbesserung soll durch eine Methode erzielt werden, die wir als MoveXY bezeichnen. Sie nimmt ein Point-Objekt vom Aufrufer entgegen und wird in GeometricObject definiert.


public void MoveXY(Point center) {
  _Center = center;
}

Da eine Struktur ein Wertetyp ist, schreiben sich die Felder X und Y der im Parameter center übergebenen Koordinaten in die gleichlautenden Felder von _Center.

Sehen wir uns nun in einem Codefragment an, wie einfach es ist, diese Methode zu benutzen. Es wird dabei davon ausgegangen, dass ein konkretes Circle-Objekt namens kreis vorliegt. Mit


Point newPoint = new Point(150, 315);
kreis.MoveXY(newPoint);

übergeben wir der Methode ein Point-Objekt. Benötigen wir dieses Objekt zur Laufzeit der Anwendung nicht mehr, kann es auch in der Argumentenliste erzeugt werden.


kreis.MoveXY(new Point(150, 315)); 

Zuletzt ergänzen wir die Klassen Circle und Rectangle noch um einen Konstruktor, der neben dem Radius eine Point-Referenz als Argument erwartet:


public Circle(double radius, Point center) : this(radius) {
  _Center = center;
}
public Rectangle(double length, double width, Point center) 
                                             : this(length, width) {
  _Center = center;
}

Damit wird eine Instanziierung der Klasse mit


Circle kreis = new Circle(2, new Point(5, 12));

möglich.


Anmerkung

Den Code des Beispiels GeometricObjectsSolution mit allen Änderungen, die wir bisher in diesem Kapitel vorgenommen haben, finden Sie auf der Buch-DVD unter ...\Kapitel 6\GeometricObjectsSolution.




Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  Zum Katalog
Zum Katalog: Visual C# 2010

Visual C# 2010
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Katalog: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: C++ Handbuch






 C++ Handbuch


Zum Katalog: C/C++






 C/C++


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2010
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.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern