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 7 Weitere Möglichkeiten von C#
Pfeil 7.1 Namensräume (Namespaces)
Pfeil 7.1.1 Zugriff auf Namespaces
Pfeil 7.1.2 Die »using«-Direktive
Pfeil 7.1.3 Globaler Namespace
Pfeil 7.1.4 Vermeiden von Mehrdeutigkeiten
Pfeil 7.1.5 Namespaces festlegen
Pfeil 7.1.6 Der ::-Operator
Pfeil 7.2 Generics – generische Datentypen
Pfeil 7.2.1 Lösung mit einer generischen Klasse
Pfeil 7.2.2 Typparameter mit Constraints einschränken
Pfeil 7.2.3 Generische Methoden
Pfeil 7.2.4 Generics und Vererbung
Pfeil 7.2.5 Konvertierung von Generics
Pfeil 7.2.6 Generische Delegates
Pfeil 7.2.7 Generische Klassen in der .NET-Klassenbibliothek
Pfeil 7.3 Operatorüberladung
Pfeil 7.3.1 Syntax der Operatorüberladung
Pfeil 7.3.2 Operatorüberladungen in »GeometricObjectsSolution«
Pfeil 7.3.3 »true«- und »false«-Operatoren
Pfeil 7.3.4 Benutzerdefinierte Konvertierungen
Pfeil 7.4 Indexer
Pfeil 7.4.1 Überladen von Indexern
Pfeil 7.4.2 Parameterbehaftete Eigenschaften
Pfeil 7.5 Erweiterungsmethoden
Pfeil 7.6 Implizit typisierte Variablen (Typinferenz)
Pfeil 7.7 Lambda-Ausdrücke
Pfeil 7.8 Anonyme Typen
Pfeil 7.9 Nullable-Typen
Pfeil 7.10 Attribute
Pfeil 7.10.1 Das »Flags«-Attribut
Pfeil 7.10.2 Anmerkungen zu den Attributen
Pfeil 7.10.3 Benutzerdefinierte Attribute
Pfeil 7.10.4 Attribute auswerten
Pfeil 7.10.5 Festlegen der Assembly-Eigenschaften
Pfeil 7.11 Partielle Methoden
Pfeil 7.12 Dynamisches Binden
Pfeil 7.12.1 Eine kurze Analyse
Pfeil 7.12.2 Dynamische Objekte
Pfeil 7.13 Unsicherer (unsafe) Programmcode – Zeigertechnik in C#
Pfeil 7.13.1 Einführung
Pfeil 7.13.2 Das Schlüsselwort »unsafe«
Pfeil 7.13.3 Deklaration von Zeigern
Pfeil 7.13.4 Die »fixed«-Anweisung
Pfeil 7.13.5 Zeigerarithmetik
Pfeil 7.13.6 Der Operator »->«


Galileo Computing - Zum Seitenanfang

7.5 Erweiterungsmethoden topZur vorigen Überschrift

Erweiterungsmethoden stellen ein wenig das strenge Konzept der Objektorientierung auf den Kopf. Unsere Aussage war bisher immer, dass die zu einer Klasse gehörenden Methoden in dieser Klasse implementiert werden müssen und an die Subklassen vererbt werden. Die in C# 3.0 eingeführten Erweiterungsmethoden weichen dieses Prinzip auf, indem auch außerhalb einer Klasse Methoden definiert werden können, die sich wie eine Instanzmethode aufrufen lassen.

Nehmen wir dazu das Beispiel der hinlänglich bekannten Klasse Circle. Vielleicht genügt uns das Angebot an Methoden nicht, weil wir noch zusätzlich gern eine Methode hätten, um auf Grundlage des Radius das Kugelvolumen zu berechnen, beispielsweise so:


Circle kreis = new Circle(5);
Console.WriteLine("Kugelvolumen = {0}", kreis.GetVolume());

Durch Bereitstellung einer Erweiterungsmethode ist das kein Problem.


static class Extensionmethods {
  // Erweiterungsmethode zur Berechnung des Kugelvolumens
  // eines Objekts vom Typ 'Circle'
  public static double GetVolume(this Circle kreis) {
    return Math.Pow(kreis.Radius, 3) * Math.PI * 4 / 3;
  }
}

Erweiterungsmethoden werden in static-Klassen implementiert und müssen selbst als public static signiert sein. Beachten Sie bitte, dass trotz der static-Definition Erweiterungsmethoden wie Instanzmethoden aufgerufen werden. Der erste Parameter in der Parameterliste muss das Schlüsselwort this vor dem ersten Parametertyp aufweisen. Hier wird der Typ angegeben, der um die genannte Methode erweitert wird. In unserem Beispiel handelt es sich um Circle. Sie können beliebig viele Erweiterungsmethoden für einen Typ schreiben, ganz so, wie Sie es benötigen. Üblicherweise werden Erweiterungsmethoden in eigens dafür vorgesehenen Klassenbibliotheken definiert.


Hinweis

Erweiterungsmethoden können auch beliebige Parameter aufweisen. Diese werden nach der Angabe der zu erweiternden Klasse definiert.


Mit Erweiterungsmethoden können Sie alle Klassen beliebig erweitern und so an Ihre spezifischen Anforderungen anpassen. Erweiterungsmethoden stellen die einzige Möglichkeit dar, sogar Klassen, die mit sealed als nicht ableitbar definiert worden sind, um eigene spezifische Methoden zu ergänzen. Eine von den Klassen, die in der Praxis häufig um Erweiterungsmethoden ergänzt werden, ist String. Selbst mit sealed signiert, gestattet String es nicht, durch Ableitungen weitere Features hinzuzufügen. Das ist im Grunde genommen sehr bedauerlich, da insbesondere die Verarbeitung von Zeichenfolgen oft nach spezifischen Gesichtspunkten erfolgen muss. Mit Erweiterungsmethoden ist das alles nun kein Problem mehr.

Dem Einsatz von Erweiterungsmethoden sind aber auch Grenzen gesetzt, denn Erweiterungsmethoden können nur public-Member der zu erweiternden Klasse aufrufen.

Wird eine Klasse um eine Erweiterungsmethode ergänzt, vererbt sich diese auch an die abgeleitete Klasse weiter. Bezogen auf unser Beispiel oben könnten Sie demnach GetVolume auch auf einem Objekt vom Typ GraphicCircle aufrufen. Hinsichtlich der Überladungsfähigkeit gelten dieselben Regeln wie bei den herkömmlichen Methoden.

Prioritätsregeln

Da Erweiterungsmethoden auch von Entwicklern geschrieben werden, die nicht Urheber der erweiterten Klasse sind, haben Erweiterungsmethoden nur eine untergeordnete Priorität. Betrachten Sie dazu das folgende Beispiel, in dem die Klasse Circle um die Methode Draw erweitert wird.


static class Extensionmethods {
  // Erweiterungsmethode zur Berechnung des Kugelvolumens
  // eines Objekts vom Typ 'Circle'
  public static double GetVolume(this Circle kreis) {
    return Math.Pow(kreis.Radius, 3) * Math.PI * 4 / 3;
  }
  // Erweiterungsmethode 'Draw'
  public static void Draw(this Circle kreis) {
    Console.WriteLine("Draw in der Erweiterungsmethode.");
  }
}

Circle ist um die Methode Draw erweitert worden, die sich an GraphicCircle weitervererbt. Da eine gleichnamige Instanzmethode in GraphicCircle existiert, muss die Entscheidung getroffen werden, welche der beiden zur Ausführung kommt: Es handelt sich definitiv um die Draw-Methode der Klasse GraphicCircle.


static void Main(string[] args) {
  Circle kreis = new Circle(5);
  kreis.Draw();
  GraphicCircle g = new GraphicCircle();
  g.Draw();
}

Die Ausgabe dieses Codefragments wird wie folgt lauten:


Draw in der Erweiterungsmethode.
Der Kreis wird gezeichnet.

Ob eine Erweiterungsmethode aufgerufen wird, hängt davon ab, ob eine gleichnamige Instanzmethode existiert. Wie Sie gesehen haben, hat eine Instanzmethode in jedem Fall Priorität vor einer gleichnamigen Erweiterungsmethode.

Die Erweiterungsmethode einer Klasse kann stets durch eine spezifischere Version ersetzt werden, die für einen Typ definiert ist. Gewissermaßen haben wir es dabei mit einer Überschreibung zu tun. Angenommen, die Klasse Object sei um die Methode Display erweitert worden. Damit steht jeder Klasse die Erweiterungsmethode zur Verfügung – soweit sie sich im aktuellen Namespace befindet oder in einem Namespace, der mit using importiert wird. Eine spezifische Version von Display kann aber auch für alle Objekte vom Typ Circle bereitgestellt werden. Die Circle-Version überdeckt in diesem Fall die geerbte Erweiterungsmethode der Klasse Object.


static class Extensionmethods {
  public static void Display(this object obj) {
    Console.WriteLine(obj.ToString());
  }
  public static void Display(this Circle kreis) {
    Console.WriteLine("Kreis mit Radius {0}", kreis.Radius);
  }
}

Die Spezialisierung einer Erweiterungsmethode für einen bestimmten Typ setzt sich auch in den abgeleiteten Klassen durch. Damit wird ein GraphicCircle-Objekt ebenfalls von der spezifischen Version profitieren, es sei denn, für den abgeleiteten Typ gibt es wiederum eine eigene Version der Erweiterungsmethode, die noch spezialisierter ist.


// Aufruf der Erweiterungsmethode 'Display'
Circle kreis = new Circle(5);
kreis.Display();
GraphicCircle g = new GraphicCircle(3);
g.Display();

Generische Erweiterungsmethoden

Erweiterungsmethoden lassen sich generisch prägen. Damit wird es möglich, eine Erweiterungsmethode beispielsweise nur für eine bestimmte Gruppe von Objekten zur Verfügung zu stellen. Der folgende Code beschreibt die Erweiterungsmethode GetFlaechen. Diese Methode erweitert alle Arrays vom Typ GeometricObject und somit auch Arrays vom Typ Circle, Rectangle usw.


class Program {
  static void Main(string[] args) {
    GeometricObject[] geoArr = new GeometricObject[3];
    geoArr[0] = new Circle(5);
    geoArr[1] = new GraphicCircle(9);
    geoArr[2] = new Rectangle(12, 7);
    geoArr.GetFlaechen();
    Console.ReadLine();
  }
}
static class Extensionmethods {
  public static void GetFlaechen<T>(this T[] objects) 
                                 where T : GeometricObject {
    foreach (GeometricObject geoObj in objects)
      Console.WriteLine(geoObj.GetFlaeche());
  }
}

Richtlinien für Erweiterungsmethoden

Mit den Erweiterungsmethoden wird uns ein sehr interessantes Feature an die Hand gegeben, um vorhandene Klassen zu erweitern. Im Allgemeinen sollten Sie aber darauf achten, dass Sie nur dann Erweiterungsmethoden implementieren, wenn es unbedingt notwendig ist. Nach Möglichkeit sollten Sie besser eine Klasse ableiten, anstatt eine Erweiterungsmethode bereitzustellen.

Wenn Sie eine Klassenbibliothek implementieren, sollten Sie es grundsätzlich vermeiden, die darin definierten Typen um Erweiterungsmethoden zu ergänzen, um das Konzept der Objektorientierung nicht unnötig aufzuweichen. Erweiterungsmethoden sind nur dann ein sinnvolles Feature, wenn Ihnen anderweitig keine Möglichkeit mehr bleibt, beispielsweise weil Sie eine sealed-, also eine nicht ableitbare Klasse erweitern möchten.

Sie sollten sich aber auch darüber im Klaren sein, dass die Versionsänderung einer Assembly dazu führen kann, dass eine zuvor für eine Klasse bereitgestellte Erweiterungsmethode wirkungslos wird, weil die entsprechende Klasse um eine gleichnamige Instanzmethode ergänzt worden ist.



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.


[Rheinwerk Computing]

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