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

Inhaltsverzeichnis
Vorwort zur 6. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Das Klassendesign
4 Vererbung, Polymorphie und Interfaces
5 Delegates und Ereignisse
6 Strukturen und Enumerationen
7 Fehlerbehandlung und Debugging
8 Auflistungsklassen (Collections)
9 Generics – Generische Datentypen
10 Weitere C#-Sprachfeatures
11 LINQ
12 Arbeiten mit Dateien und Streams
13 Binäre Serialisierung
14 XML
15 Multithreading und die Task Parallel Library (TPL)
16 Einige wichtige .NET-Klassen
17 Projektmanagement und Visual Studio 2012
18 Einführung in die WPF und XAML
19 WPF-Layout-Container
20 Fenster in der WPF
21 WPF-Steuerelemente
22 Elementbindungen
23 Konzepte von WPF
24 Datenbindung
25 Weitere Möglichkeiten der Datenbindung
26 Dependency Properties
27 Ereignisse in der WPF
28 WPF-Commands
29 Benutzerdefinierte Controls
30 2D-Grafik
31 ADO.NET – Verbindungsorientierte Objekte
32 ADO.NET – Das Command-Objekt
33 ADO.NET – Der SqlDataAdapter
34 ADO.NET – Daten im lokalen Speicher
35 ADO.NET – Aktualisieren der Datenbank
36 Stark typisierte DataSets
37 Einführung in das ADO.NET Entity Framework
38 Datenabfragen des Entity Data Models (EDM)
39 Entitätsaktualisierung und Zustandsverwaltung
40 Konflikte behandeln
41 Plain Old CLR Objects (POCOs)
Stichwort

Download:
- Beispiele, ca. 62,4 MB

Jetzt Buch bestellen
Ihre Meinung?

Spacer
Visual C# 2012 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2012

Visual C# 2012
Rheinwerk Computing
1402 S., 6., aktualisierte und erweiterte Auflage 2013, geb., mit DVD
49,90 Euro, ISBN 978-3-8362-1997-6
Pfeil 3 Das Klassendesign
Pfeil 3.1 Einführung in die Objektorientierung
Pfeil 3.2 Die Klassendefinition
Pfeil 3.2.1 Klassen im Visual Studio anlegen
Pfeil 3.2.2 Das Projekt »GeometricObjectsSolution«
Pfeil 3.2.3 Die Deklaration von Objektvariablen
Pfeil 3.2.4 Zugriffsmodifizierer einer Klasse
Pfeil 3.2.5 Splitten einer Klassendefinition mit »partial«
Pfeil 3.2.6 Arbeiten mit Objektreferenzen
Pfeil 3.3 Referenz- und Wertetypen
Pfeil 3.3.1 Werte- und Referenztypen nutzen
Pfeil 3.4 Die Eigenschaften eines Objekts
Pfeil 3.4.1 Öffentliche Felder
Pfeil 3.4.2 Datenkapselung mit Eigenschaftsmethoden sicherstellen
Pfeil 3.4.3 Die Ergänzung der Klasse »Circle«
Pfeil 3.4.4 Lese- und schreibgeschützte Eigenschaften
Pfeil 3.4.5 Sichtbarkeit der Accessoren »get« und »set«
Pfeil 3.4.6 Unterstützung von Visual Studio 2012
Pfeil 3.4.7 Automatisch implementierte Eigenschaften
Pfeil 3.5 Methoden eines Objekts
Pfeil 3.5.1 Methoden mit Rückgabewert
Pfeil 3.5.2 Methoden ohne Rückgabewert
Pfeil 3.5.3 Methoden mit Parameterliste
Pfeil 3.5.4 Methodenüberladung
Pfeil 3.5.5 Variablen innerhalb einer Methode (lokale Variablen)
Pfeil 3.5.6 Referenz- und Wertparameter
Pfeil 3.5.7 Besondere Aspekte einer Parameterliste
Pfeil 3.5.8 Zugriff auf private Daten
Pfeil 3.5.9 Die Trennung von Daten und Code
Pfeil 3.5.10 Namenskonflikte mit »this« lösen
Pfeil 3.5.11 Methode oder Eigenschaft?
Pfeil 3.5.12 Umbenennen von Methoden und Eigenschaften
Pfeil 3.6 Konstruktoren
Pfeil 3.6.1 Konstruktoren bereitstellen
Pfeil 3.6.2 Die Konstruktoraufrufe
Pfeil 3.6.3 Definition von Konstruktoren
Pfeil 3.6.4 »public«- und »internal«-Konstruktoren
Pfeil 3.6.5 »private«-Konstruktoren
Pfeil 3.6.6 Konstruktorenaufrufe umleiten
Pfeil 3.6.7 Vereinfachte Objektinitialisierung
Pfeil 3.7 Der Destruktor
Pfeil 3.8 Konstanten in einer Klasse
Pfeil 3.8.1 Konstanten mit dem Schlüsselwort »const«
Pfeil 3.8.2 Schreibgeschützte Felder mit »readonly«
Pfeil 3.9 Statische Klassenkomponenten
Pfeil 3.9.1 Statische Eigenschaften
Pfeil 3.9.2 Statische Methoden
Pfeil 3.9.3 Statische Klasseninitialisierer
Pfeil 3.9.4 Statische Klassen
Pfeil 3.9.5 Statische Klasse oder Singleton-Pattern?
Pfeil 3.10 Namensräume (Namespaces)
Pfeil 3.10.1 Zugriff auf Namespaces
Pfeil 3.10.2 Die »using«-Direktive
Pfeil 3.10.3 Globaler Namespace
Pfeil 3.10.4 Vermeiden von Mehrdeutigkeiten
Pfeil 3.10.5 Namespaces festlegen
Pfeil 3.10.6 Der »::«-Operator
Pfeil 3.10.7 Unterstützung von Visual Studio 2012 bei den Namespaces
Pfeil 3.11 Stand der Klasse »Circle«

Rheinwerk Computing - Zum Seitenanfang

3.9 Statische KlassenkomponentenZur nächsten Überschrift


Rheinwerk Computing - Zum Seitenanfang

3.9.1 Statische EigenschaftenZur nächsten ÜberschriftZur vorigen Überschrift

In der Klasse Circle sind mit Radius, XCoordinate und YCoordinate drei Eigenschaften definiert, die den Zustand eines Objekts dieses Typs beschreiben.

Jede Instanz der Klasse reserviert für ihre Daten einen eigenen Speicherbereich, der vollkommen unabhängig von den Daten anderer Objekte ist. Auch alle bisher implementierten Methoden nehmen Bezug auf Objekte, da sie mit deren Daten arbeiten.

Was ist aber, wenn Felder oder Methoden benötigt werden, die für alle Objekte einer Klasse gleichermaßen gültig sein sollen, also ohne feste Bindung an ein bestimmtes, konkretes Objekt sind? Stellen Sie sich vor, Sie beabsichtigen, in der Klasse Circle einen Zähler zu implementieren, der die Aufgabe hat, die Gesamtanzahl der Circle-Objekte festzuhalten. Ein solcher Zähler entspricht der Forderung nach einem allgemeinen, objektunabhängigen Merkmal. Um den Objektzähler zu realisieren, brauchen wir ein Feld, das unabhängig von jedem konkreten Objekt ist und nur in einer festen Bindung zur Klasse Circle steht. Der Objektzähler wäre damit als eine gemeinsame Eigenschaft aller Objekte dieses Typs zu betrachten.

Probleme dieser Art, allen typgleichen Objekten klassen-, aber nicht objektgebundene Elemente zur Verfügung zu stellen, werden von C# durch das reservierte Wort static gelöst. Bezogen auf die Forderung nach einem Objektzähler, könnte die Problemlösung wie folgt aussehen:

public class Circle {
public static int CountCircles;
[...]
}

Listing 3.42 Definition eines statischen Feldes

static deklarierte Felder sind nicht an ein bestimmtes Objekt gebunden, sondern gehören dem Gültigkeitsbereich einer Klasse an. Sie werden als Klassenvariablen bezeichnet. Demgegenüber werden an Objekte gebundene Variablen (Felder) als Instanzvariablen bezeichnet. In der Klasse Circle ist das _Radius, _XCoordinate und _YCoordinate.

Da Klassenvariablen unabhängig von jedem konkreten Objekt sind, ist es unzulässig, sie auf einer Objektreferenz aufzurufen. Stattdessen werden sie unter Angabe des Klassenbezeichners angesprochen. Den Objektzähler in Circle werten Sie daher mit

int x = Circle.CountCircles;

aus.

Für statische Felder gelten dieselben Regeln der Datenkapselung wie für Instanzvariablen. Eine Klassenvariable wie CountCircles sollte daher in derselben Weise gekapselt werden, um nicht mit dem objektorientierten Paradigma der Datenkapselung zu brechen. Dazu wird sie private deklariert. Um den Zugriff von außerhalb sicherzustellen, implementieren wir in der Klasse Circle zusätzlich eine statische Eigenschaftsmethode. Damit eine Manipulation des Zählers von außen nicht möglich ist, muss die Eigenschaft durch Verzicht auf den set-Accessor schreibgeschützt sein.

public class Circle 
{
// Klasseneigenschaft
private static int _CountCircles;
public static int CountCircles
{
get { return _CountCircles; }
}
[...]
}

Listing 3.43 Objektzähler in der Klasse »Circle«

Nun enthält die Circle-Klasse den angestrebten Objektzähler. Allerdings ist die Klassendefinition noch unvollständig, denn es fehlt die Programmlogik, um den Zähler mit jeder neuen Objektinstanz zu erhöhen. Dazu bieten sich die Konstruktoren an. Hierbei nutzen wir das Prinzip der Konstruktorverkettung und erhöhen den Objektzähler nur in dem Konstruktor, der von anderen Initialisierungsroutinen aufgerufen wird:

// Konstruktoren
public Circle() : this(0, 0, 0) { }
public Circle(int radius) : this(radius, 0, 0)) { }
public Circle(int radius, double x, double y) {
XCoordinate = x;
YCoordinate = y;
Radius = radius;
Circle._CountCircles++;
}

Listing 3.44 Erhöhung des Objektzählers

An dieser Stelle ein wichtiger Hinweis: Nehmen wir an, aus irgendwelchen Gründen wird im Konstruktor eine Ausnahme ausgelöst. Das bedeutet aber auch, dass der Konstruktoraufruf nicht korrekt zu Ende geführt wird, und hat zur Konsequenz, dass kein Objekt erstellt wird. Deshalb sollte der Zähler erst dann erhöht werden, wenn alle anderen Anweisungen bereits fehlerfrei ausgeführt worden sind, also als letzte Anweisung im Konstruktor stehen.

Im Zusammenhang mit dem Objektzähler müssen wir uns natürlich auch Gedanken über die Reduzierung des Objektzählers machen. Dazu fällt uns sofort der Destruktor ein, der sich zu diesem Zweck zunächst gut zu eignen scheint. Der Haken ist allerdings, dass Sie den Destruktor nicht aus dem Code heraus aufrufen können. Dafür ist der Garbage Collector verantwortlich. Wann der Garbage Collector aber seine Aufräumarbeiten durchführt, lässt sich nicht vorherbestimmen. Daher scheidet dieser Lösungsansatz im Grunde genommen aus.

Eine zweite Variante wäre es, den Zähler beim expliziten Aufruf einer Objektmethode zu verringern. Die Garantie, dass diese Methode aufgerufen wird, haben Sie aber ebenfalls nicht. Somit ist auch dies keine Lösung der erkannten Problematik.

Um es gleich zu sagen: Eine 100%ige Lösung gibt es nicht. Daher können Sie auch keine Gewähr für die Korrektheit der Zählerangabe übernehmen. Die insgesamt beste Lösung ist es, die beiden zuvor genannten Varianten zu kombinieren, auch wenn wir damit auf ein neues Problem stoßen: Der Destrukor und die angedeutete Objektmethode müssen synchronisiert werden, damit der Zähler nicht mehrfach reduziert wird. Wie dieser Lösungsansatz realisiert wird, werden Sie in Kapitel 4 erfahren.


Rheinwerk Computing - Zum Seitenanfang

3.9.2 Statische MethodenZur nächsten ÜberschriftZur vorigen Überschrift

Nicht nur Felder, auch Methoden können objektunabhängig sein. Für solche Methoden gilt ebenfalls, dass sie mit static signiert werden müssen. Der Aufruf dieser sogenannten Klassenmethoden erfolgt wie bei den statischen Eigenschaften auf dem Klassenbezeichner.

Klassenmethoden wurden schon häufig in den Listings dieses Buches benutzt: Es sind die Methoden WriteLine und ReadLine, die von der Klasse Console bereitgestellt werden. Auch Main ist static definiert. Ein anderer typischer Vertreter ist die Klasse Math, in der ausnahmslos alle Member static sind. Wozu sollte auch eine Instanz der Klasse Math dienlich sein, um den Sinus von 45° zu ermitteln?

Sind in einer Klasse sowohl statische als auch objektbezogene Eigenschaften bzw. Methoden definiert, unterliegt der wechselseitige Zugriff der beiden Elementtypen den folgenden beiden Regeln:

  • Aus einer Instanzmethode heraus lassen sich Klassenvariablen manipulieren und Klassenmethoden aufrufen.
  • Der umgekehrte Weg, nämlich aus einer statischen Methode heraus auf Instanzeigenschaften und Instanzmethoden zuzugreifen, ist nicht möglich. Das ist auch logisch, denn der Zugriff ist grundsätzlich nicht eindeutig, da es immer mehrere Objekte des entsprechenden Typs geben kann.

In Circle wollen wir nun auch noch ein paar Klassenmethoden bereitstellen. Hier bietet es sich zunächst an, eine allgemeine GetArea-Methode und eine klassenspezifische Methode GetCircumference zu implementieren. Damit wird es dem Benutzer der Klasse ermöglicht, die Kreisfläche oder den Kreisumfang eines x-beliebigen Kreises zu ermitteln, ohne dafür vorher ein Circle-Objekt zu erstellen.

public static double GetArea(int radius) {
return Math.PI * Math.Pow(radius, 2);
}
public double GetCircumference(int radius) {
return 2 * Math.PI * radius;
}

Listing 3.45 Klassenmethoden in der Klasse »Circle«

Beide Methoden haben allgemeingültigen Charakter, denn die erforderlichen Dateninformationen werden nicht aus einem Objekt bezogen, sondern über einen Parameter den Methoden mitgeteilt. Damit sind GetArea und GetCircumference nach den Regeln der Methodenüberladung korrekt implementiert, denn die Parameterlisten unterscheiden sich von denen der beiden Instanzmethoden. Vielleicht erinnern Sie sich noch: Modifikatoren, zu denen auch static zählt, sind kein Kriterium, das bei der Bewertung eine Rolle spielt, ob eine Methodenüberladung gültig ist oder nicht.

Darüber hinaus soll die Klasse Circle um die Methode Bigger ergänzt werden, die in der Lage ist, zwei Kreisobjekte miteinander zu vergleichen. Eine ähnliche Methode ist in Circle bereits enthalten, allerdings als Instanzmethode.

In der Methode muss natürlich ebenfalls dem Umstand Rechnung getragen werden, dass eines der beiden Übergabeargumente null ist oder sogar beide gleichzeitig.

public static int Bigger(Circle kreis1, Circle kreis2) {
if (kreis1 == null && kreis2 == null) return 0;
if (kreis1 == null) return -1;
if (kreis2 == null) return 1;
if(kreis1.Radius > kreis2.Radius) return 1;
if(kreis1.Radius < kreis2.Radius) return -1;
return 0;
}

Listing 3.46 Eine weitere Klassenmethode in »Circle«


Rheinwerk Computing - Zum Seitenanfang

3.9.3 Statische KlasseninitialisiererZur nächsten ÜberschriftZur vorigen Überschrift

Bei der Instanziierung einer Klasse wird ein Konstruktor aufgerufen. Auf Klassenbasis gibt es dazu ein Pendant, das als statischer Konstruktor oder statischer Initialisierer bezeichnet wird. Der statische Konstruktor ist eine an die Klasse gebundene Methode, die nur auf die statischen Mitglieder der Klasse Zugriff hat. Der Aufrufzeitpunkt ist zwar nicht bekannt, erfolgt aber auf jeden Fall, bevor der erste statische Member einer Klasse ausgeführt oder eine Instanz der Klasse erzeugt wird. Zudem wird der statische Konstruktor einer Klasse während eines Programmlaufs nur ein einziges Mal aufgerufen.

Die Definition des statischen Konstruktors in Circle sieht folgendermaßen aus:

static Circle() {[...]}

Beachten Sie, dass ein statischer Konstruktor keinen Zugriffsmodifizierer akzeptiert. Da ein statischer Konstruktor automatisch aufgerufen wird und niemals direkt, macht eine Parameterliste keinen Sinn – die runden Klammern sind daher grundsätzlich leer.

Statische Konstruktoren bieten sich an, um komplexe Initialisierungen vorzunehmen. Dabei könnte es sich beispielsweise um das Auslesen von Dateien oder auch um die Initialisierung statischer Arrays handeln.

Aufrufreihenfolge der Konstruktoren

Statische Klasseninitialisierer und Konstruktoren sind sich in der Funktionsweise ähnlich. Während ein Klasseninitialisierer Klassendaten bereitstellt, versorgen Konstruktoren die objektspezifischen Felder mit Daten. Sobald Sie eine Objektvariable deklarieren, wird der statische Konstruktor ausgeführt und erst danach der Konstruktor. Im Bedarfsfall dürfen Sie also im Konstruktor Code implementieren, der die vorhergehende Initialisierung der statischen Klassenmitglieder voraussetzt.


Rheinwerk Computing - Zum Seitenanfang

3.9.4 Statische KlassenZur nächsten ÜberschriftZur vorigen Überschrift

Es gibt Klassen, die nur statische Mitglieder enthalten. Meistens handelt es sich dabei um Klassen, die allgemeingültige Operationen bereitstellen. In der .NET-Klassenbibliothek gibt es davon einige, die Klasse Math gehört auch dazu. Ein besonderes Merkmal statischer Klassen ist, dass sie nicht instanziiert werden können.

Das folgende Listing zeigt die benutzerdefinierte Klasse Mathematics, die die beiden Methoden Add und Subtract definiert.

public static class Mathematics {
public static double Add(params double[] values)
{
[...]
}
public static double Subtract(params double[] values) {
[...]
}
[...]
}

Listing 3.47 Beispiel einer statischen Klasse

Der Aufruf statischer Klassen erfolgt unter Angabe des Klassenbezeichners, bezogen auf die Klasse Mathematics also mit:

Mathematics.Add(2, 77, 99);

Wenn Sie static als Modifizierer einer Klasse angeben, müssen Sie die folgenden Punkte beachten:

  • Statische Klassen dürfen nur statische Klassenmitglieder haben. Der Modifizierer static ist auch bei den Membern anzugeben.
  • Statische Klassen enthalten keine Konstruktoren und können deshalb auch nicht instanziiert werden. Der parameterlose Konstruktor ist implizit private.

Rheinwerk Computing - Zum Seitenanfang

3.9.5 Statische Klasse oder Singleton-Pattern?Zur vorigen Überschrift

Eine statische Klasse ist sinnvoll, wenn Sie keine Instanziierung der Klasse zulassen wollen. Man könnte auch sagen, in der Anwendung gibt es nur ein Objekt dieses Typs, obwohl der Begriff »Objekt« im Zusammenhang mit statischen Klassen nicht präzise verwendet wird. Dasselbe Ziel wird auch von einem Design Pattern verfolgt, das als Singleton-Pattern bekannt ist.

Als Design Pattern bezeichnet man allgemein verwendbare Lösungsansätze für immer wiederkehrende Probleme im Umfeld eines Softwareentwurfs. Design Patterns beschreiben also im weitestgehenden Sinn Schablonen, die in einem bestimmten Kontext einer Software immer wieder verwendet werden können.

Betrachten wir das Singleton-Pattern an dem konkreten Beispiel der Klasse Demo. Ergänzend zum allgemein verwendeten Pattern beschreibt die Klasse zu Demonstrationszwecken mit Value eine Eigenschaft.

public class Demo {
private static Demo _Instance = null;
public int Value { get; set;}
private Demo() { }
public static Demo Instance {
get {
if (_Instance == null) {
_Instance = new Demo();
}
return _Instance;
}
}
}

Listing 3.48 Klassendesign nach dem Singleton-Pattern

Werfen wir einen Blick in die Klassendefinition. Es fällt auf, dass der parameterlose Standardkonstruktor private implementiert ist. Da kein weiterer Konstruktor in der Klasse enthalten ist, kann die Klasse nicht instanziiert werden. In der Klasse ist ein statisches Feld vom Typ Demo definiert. Sie erinnern sich, statische Member können in einer laufenden Anwendung nur einmal existieren. Mit Instance enthält die Klasse Demo auch eine statische Methode. Der Clou ist, dass innerhalb der Methode das statische Feld dahingehend geprüft wird, ob es ein konkretes Demo-Objekt beschreibt oder null ist. Im letztgenannten Fall wird ein Demo-Objekt erzeugt und die Referenz im statischen Feld _Instance gespeichert. Hat das statische Feld jedoch nicht den Inhalt null, handelt es sich um ein Demo-Objekt, dessen Referenz an den Aufrufer der Methode Instance zurückgeliefert wird.

Nein, es ist kein Widerspruch darin zu sehen, dass die Klasse keinen öffentlichen Konstruktor enthält und plötzlich dennoch ein Objekt erzeugen kann. Der Konstruktor ist natürlich innerhalb der Klasse aufrufbar, somit kann auch ein Objekt erzeugt werden. Die Logik der Methode Instance garantiert jedoch, dass nur einmal ein Demo-Objekt erzeugt werden kann.

Prüfen lässt sich die Klasse ganz simpel mit dem folgenden Listing:

Demo demo = Demo.Instance;
demo.Value = 128;
Demo demo1 = Demo.Instance;
Console.WriteLine(demo1.Value);

Listing 3.49 Testen eines Singleton-Klassendesigns

Trotz des zweimaligen Aufrufs von Instance wird an der Konsole der Wert 128 ausgegeben – der Beweis dafür, dass tatsächlich nur ein Demo-Objekt existiert.

Dasselbe Ergebnis können wir auch erzielen, wenn wir eine statische Klasse bereitstellen. Dabei können wir sogar auf die Methode Instance verzichten, der Code wird also einfacher. Welche Vorteile und Nachteile zwischen dem Singleton-Pattern und einer statischen Klassendefinition sind also zu notieren? Im Grunde genommen beschränken sich die Unterschiede auf zwei wesentliche Punkte:

  • Bei Verwendung des Singleton-Patterns wird tatsächlich ein Objekt erzeugt, das zu einem späteren Zeitpunkt vom Garbage Collector zerstört werden muss. Eine statische Klasse beschreibt hingegen kein Objekt und fällt damit auch nicht in den Aufgabenbereich des Garbage Collectors. Ein Pluspunkt für die statische Klasse.
  • Statische Klassen können nicht abgeleitet werden. Auch wenn uns die damit im Zusammenhang stehende Vererbung thematisch erst im nächsten Kapitel beschäftigen wird, sei dieser Punkt, der generell als ein Nachteil bewertet werden muss, an dieser Stelle erwähnt.


Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Visual C# 2012

Visual C# 2012
Jetzt Buch bestellen


 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Rheinwerk-Shop: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Rheinwerk-Shop: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Rheinwerk-Shop: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: C++ Handbuch






 C++ Handbuch


Zum Rheinwerk-Shop: C/C++






 C/C++


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo





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