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 3 Klassendesign
Pfeil 3.1 Einführung in die Objektorientierung
Pfeil 3.1.1 Vorteile der objektorientierten Programmierung
Pfeil 3.2 Klassendefinition
Pfeil 3.2.1 Klassen in Visual Studio anlegen
Pfeil 3.2.2 Das Projekt »GeometricObjectsSolution«
Pfeil 3.2.3 Deklaration von Objektvariablen
Pfeil 3.2.4 Zugriffsmodifizierer einer Klasse
Pfeil 3.2.5 Splitten einer Klassendefinition mit »partial«
Pfeil 3.3 Arbeiten mit Objektreferenzen
Pfeil 3.3.1 Prüfen auf Initialisierung
Pfeil 3.3.2 Ein Objekt freigeben
Pfeil 3.3.3 Mehrere Referenzen auf ein Objekt
Pfeil 3.4 Referenz- und Wertetypen
Pfeil 3.5 Eigenschaften eines Objekts
Pfeil 3.5.1 Öffentliche Felder
Pfeil 3.5.2 Datenkapselung mit Eigenschaftsmethoden sicherstellen
Pfeil 3.5.3 Ergänzung der Klasse »Circle«
Pfeil 3.5.4 Lese- und schreibgeschützte Eigenschaften
Pfeil 3.5.5 Sichtbarkeit der Accessoren »get« und »set«
Pfeil 3.5.6 Unterstützung von Visual Studio 2010
Pfeil 3.5.7 Automatisch implementierte Eigenschaften
Pfeil 3.5.8 Vereinfachte Objektinstanziierung mit Objektinitialisierern
Pfeil 3.6 Methoden eines Objekts
Pfeil 3.6.1 Methoden mit Rückgabewert
Pfeil 3.6.2 Methoden ohne Rückgabewert
Pfeil 3.6.3 Methoden mit Parameterliste
Pfeil 3.6.4 Methodenüberladung
Pfeil 3.6.5 Variablen innerhalb einer Methode (Lokale Variablen)
Pfeil 3.6.6 Referenz- und Wertparameter
Pfeil 3.6.7 Zugriff auf private Daten
Pfeil 3.6.8 Namenskonflikte mit »this« lösen
Pfeil 3.6.9 Trennung von Daten und Code im Speicher
Pfeil 3.6.10 Methode oder Eigenschaft?
Pfeil 3.6.11 Methoden und Eigenschaften umbenennen
Pfeil 3.7 Konstruktoren
Pfeil 3.7.1 Konstruktoren bereitstellen
Pfeil 3.7.2 Parametrisierte Konstruktoren und die Objektinitialisierung
Pfeil 3.7.3 Konstruktoraufrufe
Pfeil 3.7.4 Definition von Konstruktoren
Pfeil 3.7.5 »internal«-Konstruktoren
Pfeil 3.7.6 »private«-Konstruktoren
Pfeil 3.7.7 Konstruktorenaufrufe umleiten
Pfeil 3.8 Der Destruktor
Pfeil 3.9 Konstanten in einer Klasse
Pfeil 3.9.1 Konstanten mit dem Schlüsselwort »const«
Pfeil 3.9.2 Schreibgeschützte Felder mit »readonly«
Pfeil 3.10 Statische Klassenkomponenten
Pfeil 3.10.1 Begrifflichkeiten
Pfeil 3.10.2 Statische Klassenvariable in der Klasse »Circle«
Pfeil 3.10.3 Klassenspezifische Methoden
Pfeil 3.10.4 Statische Konstruktoren (Klasseninitialisierer)
Pfeil 3.10.5 Statische Klassen
Pfeil 3.10.6 Stand der Klasse »Circle«


Galileo Computing - Zum Seitenanfang

3.5 Eigenschaften eines Objekts Zur nächsten ÜberschriftZur vorigen Überschrift


Galileo Computing - Zum Seitenanfang

3.5.1 Öffentliche Felder Zur nächsten ÜberschriftZur vorigen Überschrift

Das Objekt eines bestimmten Typs unterscheidet sich von anderen typgleichen Objekten durch seine charakterisierenden Eigenschaften. So wie sich eine Person von jeder anderen durch den Namen, die Augenfarbe, das Alter, das Geschlecht, den Wohnort und viele andere Werte unterscheidet, unterscheidet sich ein Circle-Objekt von anderen Circle-Objekten durch seinen Radius, vielleicht auch durch seine Position und seine Farbe.

Eigenschaften werden durch Daten beschrieben. Welche das genau sind, hängt nur von den Anforderungen ab, die an das Objekt gestellt werden. Soll ein Circle-Objekt nicht gezeichnet werden, wird vermutlich die darstellende Farbe keine Bedeutung haben. Auf diese Eigenschaft kann dann verzichtet werden.

Alle im Programm notwendigen Objekteigenschaften müssen in der Klassendefinition Berücksichtigung finden. Ausgedrückt werden sie durch Variablen, die in der Klasse definiert sind. Um ein Circle-Objekt durch einen Radius und seine Positionskoordinaten zu charakterisieren, müssten Sie die Klassendefinition wie folgt schreiben:


public class Circle {
  public int XCoordinate;
  public int YCoordinate;
  public double Radius;
}

Eigenschaften sind Variablen, die innerhalb einer Klasse definiert sind, und werden auch als Felder bezeichnet. Der Zugriffsmodifizierer, hier public, beschreibt die Sichtbarkeit der Eigenschaft. In unserem Beispiel sind die drei Eigenschaften ohne jegliche Einschränkung überall sichtbar. Grundsätzlich kann der Datentyp einer Eigenschaft beliebig sein. Es kann sich um einen elementaren Datentyp wie int oder string handeln, aber durchaus auch um ein Array oder einen benutzerdefinierten Typ, also zum Beispiel um eine Klasse, die Sie selbst in Ihrem Programmcode geschrieben haben.

Ein auf einem elementaren Datentyp basierendes Feld hat von Anfang an einen Standardinitialisierungswert. Damit der Programmcode besser zu lesen ist, ist es nicht unüblich, bei Feldern den Standardwert trotzdem anzugeben. Das führt uns zu den folgenden Felddefinitionen in der Klasse Circle:


public class Circle {
  public int XCoordinate;
  public int YCoordinate;
  public double Radius;
}


Hinweis

Felder haben immer einen konkreten Initialisierungswert, auch wenn er nicht explizit genannt wird. Beispielsweise weisen alle Datentypen, die Zahlen beschreiben, den Startwert 0 oder 0,0 auf, Referenztypen den Wert null. Ob Sie ein Feld mit

public double Radius;

oder

public double Radius = 0;

deklarieren, ist gleich. Manchmal sorgt aber die explizite Zuweisung eines Startwerts für eine bessere Lesbarkeit des Programmcodes.


Der Zugriff auf eine Eigenschaft ist nicht schwierig. Instanziieren Sie zuerst die Klasse, damit Sie ein Objekt haben, und geben Sie danach die Eigenschaft, getrennt durch einen Punkt von der Objektvariablen, an.


Circle kreis = new Circle();
kreis.Radius = 10;

Jetzt hat das Circle-Objekt einen Radius von 10 Einheiten. Sehr ähnlich wird auch der Wert einer Eigenschaft ausgewertet.


double dbl = kreis.Radius;

Der Aufruf der Eigenschaft bewirkt die Rückgabe des in ihr gespeicherten Werts. Sie können ihn, wie gezeigt, einer Variablen zuweisen oder direkt verarbeiten, beispielsweise durch Ausgabe an der Konsole.


Console.WriteLine("Der Kreisradius beträgt {0}", kreis.Radius);


Galileo Computing - Zum Seitenanfang

3.5.2 Datenkapselung mit Eigenschaftsmethoden sicherstellen Zur nächsten ÜberschriftZur vorigen Überschrift

Wenn Sie die Eigenschaft Radius etwas genauer analysieren, werden Sie auf Probleme stoßen, denen bisher noch keine Aufmerksamkeit geschenkt worden ist. Was ist beispielsweise, wenn mit


kreis.Radius = -12;

dem Radius eine negative Zahl übergeben wird? Sie werden mir zustimmen, dass ein negativer Wert nicht akzeptiert werden kann. Was müssen wir also tun, um die Bedingung


Radius >=  0 

zu erfüllen? Grundsätzliche Denkansätze zur Lösung dieses Problems gibt es mehrere:

  • Eine erste Idee könnte sein, einen Datentyp zu wählen, der nur den positiven Zahlenbereich abdeckt. Eine solche Lösung ist jedoch schlecht, da diese Datentypen bis auf byte nicht CLS-konform sind.
  • Die Eingabe könnte auch vor der Zuweisung an die Eigenschaft des Objekts mit einer if-Anweisung geprüft werden:
int radius = Convert.ToDouble(Console.ReadLine());
if (radius >= 0)
kreis.Radius = radius;
    • Dieser Lösungsansatz entspricht zwar der Forderung, dass ein Kreisradius nicht negativ sein kann, ist aber ebenfalls inakzeptabel. Was ist, wenn sich die Bedingung später ändert, weil beispielsweise ein bestimmter Mindestradius vorgeschrieben wird? Alle Zuweisungen des Programmcodes an die Eigenschaft Radius müssten entsprechend angepasst werden. Wird nur eine einzige übersehen, arbeitet das Programm fehlerhaft.
  • Nach der Argumentation in den vorhergehenden beiden Punkten bleibt nur noch eine Alternative, die auch den optimalen Lösungsansatz darstellt: die Prüfung der Eingabe im Klassencode.

Um den letztgenannten Punkt zu realisieren, bieten sich Eigenschaftsmethoden an. Eigenschaftsmethoden können Sie sich als Container für zwei Subroutinen mit jeweils einem eigenen Anweisungsblock vorstellen: get und set. Der get-Block wird bei der Auswertung der Eigenschaft ausgeführt, der set-Block, wenn der Eigenschaft ein Wert zugewiesen werden soll.

Sehen wir uns die vollständige Implementierung der Eigenschaftsmethode Radius an, die die Forderung erfüllt, die Zuweisung eines negativen Radius an ein Circle-Objekt zu verhindern und nur einen zulässigen Wert zu speichern:


public class Circle {
  private double _Radius;
  // Eigenschaftsmethode
  public double Radius {
    get {
      return _Radius; 
    }
    set {
      if (value >= 0)
        _Radius = value;
      else
        Console.Write("Unzulässiger negativer Wert.");
    }
  }
  ...
}

Der Wert für den Radius wird weiterhin in einem Feld gespeichert. Dieses ist nun allerdings nicht mehr als public definiert, sondern als private. Damit wird sichergestellt, dass von außerhalb der Klasse Circle das Feld weder sichtbar ist noch manipuliert werden kann. Ganz allgemein wird dieses Prinzip als Datenkapselung bezeichnet.


Hinweis

Die Datenkapselung ist eines der Schlüsselkonzepte der objektorientierten Programmierung, zu der auch noch die später zu behandelnde Vererbung und die Polymorphie gehören.


Da die öffentliche Eigenschaftsmethode Radius lautet, muss das private Feld aus Gründen der Eindeutigkeit umbenannt werden. Üblicherweise beginnen private Felder entweder mit einem Kleinbuchstaben oder es wird der Bezeichner herangezogen, dem ein Unterstrich vorangestellt wird, hier _Radius.

Wenn Sie der Eigenschaft Radius mit


kreis.Radius = 10;

einen Wert zuweisen, wird in der Eigenschaftsmethode automatisch der set-Zweig ausgeführt:


set {
  if (value >= 0)
    _Radius = value;
  else
    Console.Write("Unzulässiger negativer Wert.");
}

Der zugewiesene Wert, hier 10, wird von einem impliziten Parameter entgegengenommen, der grundsätzlich value heißt. Der Datentyp von value entspricht dem Datentyp der Eigenschaft. In unserem Beispiel ist value demnach vom Typ double. Innerhalb des set-Anweisungsblocks können die Anweisungen programmiert werden, die den zu übergebenden Wert auf seine Zulässigkeit hin überprüfen. Natürlich können Sie auch beliebige andere Operationen in set codieren, beispielsweise eine Überprüfung, ob der aktuelle Benutzer überhaupt berechtigt ist, den Eigenschaftswert festzulegen. Hinsichtlich des operativen Verhaltens sind keine Grenzen gesetzt.

Die Auswertung der Eigenschaft mit


double x = kreis.Radius;

führt zum Aufruf des get-Blocks innerhalb der Eigenschaftsmethode:


get {
  return _Radius; 
}

Meistens enthält der get-Block, ähnlich wie in unserem Beispiel, nur eine return-Anweisung, die den Inhalt des gekapselten Feldes an den Aufrufer zurückgibt. Aber selbstverständlich dürfen Sie auch beliebige weitere Operationen implementieren.


Galileo Computing - Zum Seitenanfang

3.5.3 Ergänzung der Klasse »Circle« Zur nächsten ÜberschriftZur vorigen Überschrift

In ähnlicher Weise, wie wir die Eigenschaft Radius implementiert haben, sollten wir auch die beiden öffentlichen Felder XCoordinate und YCoordinate durch Eigenschaftsmethoden ersetzen.


public class Circle {
  // ---------- Felder -------------
  private double _Radius;
  private int _XCoordinate;
  private int _YCoordinate;
  // -------- Eigenschaftsmethoden ----------
  public int YCoordinate {
    get { return _YCoordinate; }
    set { _YCoordinate = value; }
  }
  public int XCoordinate {
    get { return _XCoordinate; }
    set { _XCoordinate = value; }
  }
  public double Radius {
    get { return _Radius; }
    set {
      if (value >= 0)
        _Radius = value;
      else
        Console.WriteLine("Unzulässiger negativer Radius.");
    }
  }
}


Galileo Computing - Zum Seitenanfang

3.5.4 Lese- und schreibgeschützte Eigenschaften Zur nächsten ÜberschriftZur vorigen Überschrift

Es kommt häufig vor, dass eine Eigenschaft entweder schreib- oder lesegeschützt sein muss. Die Realisierung ist denkbar einfach: Sie erstellen eine schreibgeschützte Eigenschaft ohne set-Block. Eine so definierte Eigenschaft kann nur über get ausgewertet werden.


...
private int _MyProperty;
// schreibgeschützte Eigenschaft
public int MyProperty {
  get { return _MyProperty; }
}
...

Ein Benutzer der Klasse kann einer schreibgeschützten Eigenschaft mit einer üblichen Zuweisung keinen Wert übergeben, daher muss es einen anderen Weg geben. Dieser führt in der Regel über den Aufruf einer anderen Methode der Klasse. Häufig werden die Werte gekapselter Felder von schreibgeschützten Eigenschaften bei der Initialisierung des Objekts im Konstruktor festgelegt.

Soll eine Objekteigenschaft zur Laufzeit einer Anwendung lesegeschützt sein, darf die Implementierung der Eigenschaft nur den set-Block enthalten.


...
private int _MyProperty;
// Lesegeschützte Eigenschaft
public int MyProperty {
  set { _MyProperty = value; }
}
...

Der Wert einer lesegeschützten Eigenschaft kann selbstverständlich durch eine andere Methode der Klasse zurückgegeben werden, die das gekapselte Feld auswertet.


Galileo Computing - Zum Seitenanfang

3.5.5 Sichtbarkeit der Accessoren »get« und »set« Zur nächsten ÜberschriftZur vorigen Überschrift

Wird keine andere Angabe gemacht, entspricht die Sichtbarkeit der beiden Accessoren get und set per Vorgabe der Sichtbarkeit der Eigenschaftsmethode. Ist die Eigenschaftsmethode als public definiert, sind get und set automatisch ebenfalls public. Jeder Accessor darf auch eine individuelle Sichtbarkeit aufweisen. Damit lässt sich der jeweilige Zugriff feiner steuern.


public int MyProperty {
  internal get {
    return this.someValue;
  }
  set {
    this.someValue = value;
  }
}

In diesem Codefragment ist die Eigenschaft MyProperty öffentlich definiert. Der set-Accessor hat keinen abweichenden Zugriffsmodifizierer und ist somit ebenfalls public. Im Gegensatz dazu schränkt der Zugriffsmodifizierer internal das Auswerten der Eigenschaft auf die aktuelle Anwendung ein.

Beabsichtigen Sie, abweichend vom Zugriffsmodifizierer der Eigenschaftsmethode einen der beiden Accessoren mit einem anderen, individuellen Zugriffsmodifizierer zu spezifizieren, gelten die folgenden Regeln:

  • In der Eigenschaftsmethode müssen beide Accessoren definiert sein.
  • Nur bei einem der beiden Accessoren darf ein Zugriffsmodifizierer angegeben werden, der vom Zugriffsmodifizierer der Eigenschaftsmethode abweicht.
  • Der Zugriffsmodifizierer des Accessors muss einschränkender sein als der der Eigenschaftsmethode.

In der Praxis sind individuelle Zugriffsmodifizierer bei den Accessoren allerdings selten anzutreffen.


Galileo Computing - Zum Seitenanfang

3.5.6 Unterstützung von Visual Studio 2010 Zur nächsten ÜberschriftZur vorigen Überschrift

Es ist etwas mühevoll, die Struktur einer Eigenschaftsmethode zu schreiben. Sie können diese Aufgabe Visual Studio 2010 übertragen, indem Sie zuerst ein öffentliches Feld deklarieren, das bereits den Bezeichner aufweist, den das spätere gekapselte Feld haben soll, beispielsweise:


public double _Radius;

Gehen Sie anschließend mit dem Eingabecursor in den Feldbezeichner, oder markieren Sie den Bezeichner komplett. Öffnen Sie nun das Kontextmenü mit der rechten Maustaste, und wählen Sie Umgestalten und dann Feld kapseln. Nach Bestätigung wird Visual Studio die Eigenschaftsmethode mit den set- und get-Zweigen automatisch generieren. Dabei wird, in diesem Beispiel, die Eigenschaftsmethode den Bezeichner Radius haben. Gleichzeitig wird auch die Grundfunktionalität (Wertübergabe und Wertrückgabe) erzeugt.


Galileo Computing - Zum Seitenanfang

3.5.7 Automatisch implementierte Eigenschaften Zur nächsten ÜberschriftZur vorigen Überschrift

Daten sollten grundsätzlich gekapselt werden. Mit anderen Worten bedeutet dies, dass Sie ein als private deklariertes Feld anlegen und den Zugriff darauf mit einer Eigenschaftsmethode und deren beiden Accessoren get und set steuern.

Nicht selten werden Sie aber Objekteigenschaften benötigen, ohne dass Code in set und get notwendig ist. Ein gutes Beispiel dafür liefert die Klasse Circle:


public class Circle {
  private int _XCoordinate;
  private int _YCoordinate;
  ...
  public int XCoordinate {
    get { return _XCoordinate; }
    set { _XCoordinate = value; }
  }
  public int YCoordinate {
    get { return _YCoordinate; }
    set { _YCoordinate = value; }
  }
}

In solchen Fällen lässt sich der Programmcode reduzieren, wenn Sie ein Feature benutzen, das mit C# 3.0 eingeführt worden ist. Es handelt sich dabei um die automatisch implementierten Eigenschaften. Mit dieser Spracherweiterung ist es möglich, die oben gezeigten Eigenschaften wie folgt zu implementieren:


public class Circle {
  public int XCoordinate {get; set;}
  public int YCoordinate {get; set;}
  ...
}

Hierbei wird das notwendige private Feld implizit bereitgestellt. get und set erlauben keinen Programmcode. Sie dürfen aber einen der beiden Zweige mit einem einschränkenden Zugriffsmodifizierer ausstatten, beispielsweise wenn Sie eine schreibgeschützte Eigenschaft bereitstellen wollen.


// fehlerhafter Programmcode
public class Circle {
  public int XCoordinate {get; internal set;}
  public int YCoordinate {get; internal set;}
  ...
}

Das Weglassen des get- oder set-Accessors ist nicht erlaubt.


Galileo Computing - Zum Seitenanfang

3.5.8 Vereinfachte Objektinstanziierung mit Objektinitialisierern topZur vorigen Überschrift

Um einem Circle-Objekt spezifische Daten zuzuweisen, schreiben Sie den folgenden Code:


Circle kreis = new Circle();
kreis.XCoordinate = 23;
kreis.YCoordinate = 100;
kreis.Radius = 5;

Es geht aber auch etwas einfacher: Sie können die Startwerte in derselben Anweisungszeile in geschweiften Klammern angeben, wie das folgende Beispiel zeigt:


Circle kreis = new Circle() { XCoordinate = 23, 
                              YCoordinate = 100, 
                              Radius = 5};

Dabei müssen Sie nicht zwangsläufig alle Eigenschaften angeben. Felder, denen kein spezifischer Wert übergeben wird, werden mit dem typspezifischen Standardwert initialisiert. Beachten Sie bitte, dass die einzelnen Eigenschaften durch ein Komma voneinander getrennt werden. Sie können mit dieser Notation sogar auf die runden Klammern verzichten, z. B.:


Circle kreis = new Circle {XCoordinate = 23, 
                           YCoordinate = 100, Radius = 5};

Die IntelliSense-Liste unterstützt Sie bei dieser Initialisierung und zeigt Ihnen genau die Eigenschaften an, die noch nicht initialisiert sind.



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