Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript...

177
Skript zur Vorlesung Programmierung II Einführung in C# Fachbereich Elektrotechnik & Infromatik Prof. Dr. Uwe Hartmann Fachhochschule Stralsund

Transcript of Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript...

Page 1: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Skript zur Vorlesung

Programmierung II

Einführung in C#

Fachbereich Elektrotechnik & Infromatik Prof. Dr. Uwe HartmannFachhochschule Stralsund

Page 2: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 2 -

1 Einleitung

C C++ C#

keine OOP OOP möglich nur OOP

AlgolPascalFortran

Algol68 (Überladung)Simula (Klassen) Java (OOP, virtuelle Maschine)

Visual C++ Visual Studio.NET Framework

1.1 Objektorientierte Softwareentwicklung

Funktionale Programmierung (Softwareentwicklung)

Abläufe eines Anwendungsbereiches werden schrittweise in Algorithmen umgesetzt

Objektorientierte Programmierung (Softwareentwicklung)

Objekte eines Anwendungsbereiches und ihre Beziehungen zueinander werden beschrieben und klassifiziert

Merkmale von Objekten

− statische Merkmale: Zustände (--> Daten)

− dynamische Merkmale: Verhalten (-->Algorithmen)

Klasse (extensional)

Zusammenfassung von Objekten

Klasse (intensional) = abstrakter Datentyp

Beschreibung der Merkmale der Klassenobjekte durch

− Datentypen (statische Merkmale, Zustände) und

− Funktionen (dynamische Merkmale, Algorithmen)

Problemstellung bei der objektorientierten Softwareentwicklung

Definition/Finden geeigneter Klassen und ihrer Beziehungen zueinander zur Abbildung der relevanten Objekte eines Anwendungsbereiches in einer Anwendung

Page 3: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 3 -

1.2 .NET-Framework

Klassischer Übersetzungsprozeß

Quellcode (test.cpp)

Compiler/Linker

Maschinencode (test.exe)

.NET-Framework

Sprachunabhängigkeit

− durch Common Language Spezification (CLS) und Common Type System (CTS).

− Erzeugung von Zwischencode (ähnlich Java)

Plattformunabhängigkeit

Spezifikation der Common Language Runtime (CLR) für unterschiedliche Plattformen

Speicherverwaltung im Hintergrund

Garbage Collector gibt nicht mehr benötigten Heap-Speicherplatz selbständig frei

Einheitliches Fehlerkonzept

Verwendung von Exceptions

Objektorientiertheit

.NET ist 100%ig objektorientiert. Alle Elemente werden auf Objekte zurückgeführt.

Übersetzungsprozeß in .NET

Quellcode (test.cs)

CompilerAssembly (test.exe)

Quellcode (test.vb)

.

.

. Maschinencode(sofort ausgeführt)JITter

Bibliotheken (.dll)

Assembly

Page 4: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 4 -

− enthält MSIL-Code (Microsoft Intermediate Language; kurz IL-Code)

− enthält Manifest, das Informationen über

− Name, Version, Speicherort des Assembly

− Namen aller Dateien, die zur Komponente gehören

− Beschreibung aller Typen, die im Assembly definiert sind

− Namen der assemblies, auf die zugegriffen wird

enthält

− enthält Metadaten mit Informationen über alle Klassen incl. Methoden und Eigenschaften und sonstige Datentypen

JITter

Just-In-Time-Compiler überführt IL-Code in Maschinencode

1.3 Programmaufbau

Beispiel (C/C++)

#include <stdio.h>int main(int argc, char* argv[]){

printf("Hello World");return 0;

}

Beispiel 1.3.a

using System;using System.Collections.Generic;using System.Text;namespace Beispiel{

class Program{

static void Main(string[] args){

Console.WriteLine("Hello World");}

}}

• jedes ausführbare Programm besitzt genau eine Klasse mit einer Methode Main() als Einstiegspunkt für die Programmausführung

Syntax

Page 5: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 5 -

compilation-unit

using-directive namespace-declaration

enum-declaration

struct-declaration

class-declaration

interface-declaration

delegate-declaration

type-declaration

using-directive

namespace-nameusing ;

namespace-declaration

using-directive namespace-declaration

type-declaration

namespace-namenamespace { }

type-declaration

Page 6: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 6 -

Namensraum (namespace)

• Ein Namensraum ist eine logische Organisationsstruktur, die verschiedene Typdefinitionen (insbes. Klassendeklarationen) zusammenfaßt

− Stilregel: Ein Typ sollte immer zu einem Namensraum gehören

− Namensräume können unabhängig von der Klassenhierarchie selbst hierarchisch geordnet sein

− Wurzel aller Namensräume: 'System'

• alle in namespace definierten Typen (insbes. Klassen) gehören zu dem Namensraum

• vollständiger Name eines Typs ist dann

<namespace-name> . [ <namespace-name> . ]... <type-name>

System.Console.WriteLine ("Hallo World")

Namensraum Klasse Methode

• Namensräume können dem Programm durch using-Klausel bekanntgemacht werden. Dann kann die Angabe des Namensraumes im Typnamen entfallen

Beispiel

Aufruf der Methode WriteLine bei bekanntem Namensraum System (using System;):

Console.WriteLine("Hello World")

• innerhalb von Namensräumen lassen sich nur Aufzählungen, Strukturen, Klassen, Schnittstellen und Delegaten deklarieren

• Felder (Daten) und Methoden (Funktionen) können ausschließlich in Klassen (im Spezialfall in Strukturen) definiert werden

• Stilregel: Eine Klasse oder Struktur sollte immer in einer eigenen gleichnamigen Datei implementiert werden

Page 7: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 7 -

Zugriffsmodifizierer

Syntax

access-modifier

public

protected

internal

protected internal

private

• Der Zugriffsmodifizierer (access-modifier) gibt an, wieweit sich die Sichtbarkeit einer Typdeklaration (struct, class, ...) oder einer Memberdeklaration (field, method, ...) erstreckt:

publickeine Zugriffsbeschränkungen

protectedder Zugriff beschränkt sich auf die Klasse, in der das Member deklariert wurde (umgebende Klasse) und die von dieser Klasse abgeleiteten Typen

internalder Zugriff ist auf die Anwendung (Assembly) beschränkt, in der der Typ definiert ist

protected internalder Zugriff ist auf die Anwendung (Assembly) und hier auf die Klasse, in der das Member deklariert wurde (umgebende Klasse) und die von dieser Klasse abgeleiteten Typen beschränkt

privateZugriff nur innerhalb der deklarierenden Klasse oder der Struktur möglich

• Regel

Eine direkt in einer Namespace-Deklaration enthaltene Typ-Deklaration kann nur die Zugriffsmodifizierer public oder internal besitzen. Default ist internal.

Page 8: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 8 -

• Betrachten eines Assembly mit dem Tool MSIL-Disassembler (ILDasm) möglich

Beispiel

Manifest des Beispiel-Programms

MSIL-Code der Main-Methode

Metadaten der Main-Methode

Page 9: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 9 -

Kommentare

• /// vor einer Definition erzeugt im Visual Studio einen Kommentarrahmen, der dann selbständig ausgefüllt werden kann. Diese Kommentare dienen der Erzeugung von XML-Dokumentationen

Beispiel 1.3.b

Beispiel.csnamespace Beispiel{

/// <summary>/// Das ist eine Testklasse/// </summary>class Test{

/// <summary>/// Das ist eine Testmethode/// </summary>/// <param name="x"></param>/// <param name="y"></param>/// <returns></returns>public int TestMethod(int x, int y){

return x+y;}static void Main(string[] args){}

}}

Beispiel.XML

Page 10: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 10 -

2. C#-Typsystem

2.1 Typhierarchie

Datentypen (object)

Wertetypen

Referenztypen

Einfache Typen (außer string und object)

Aufzählungstypen (enum)

Strukturen (struct)

Schnittstelle (interface)

Arrays (array)

Delegate (delegate)

Klassentypen

object

Zeichenketten (string)

Klassen (class)

• Unterscheidung

− Elementare Typen sind Bestandteil der Sprache C# (int, double, string ...)

− Benutzerdefinierte Typen (struct, array, class, ...)

• alle Datentypen sind von dem elementaren Datentyp object abgeleitet

Page 11: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 11 -

2.2 Elementare Datentypen

• strikten Objektorientierung in C#: auch elementare Datentypen sind Objekte

Datentyp CLS Größe Bereichbyte ja 1 0 ... 255sbyte nein 1 -128 ... 127short ja 2 -32768 ... 32767ushort nein 2 0 ... 65536int ja 4 -231 ... 231-1uint nein 4 0 ... 232-1long ja 8 -263 ... 263-1ulong nein 8 0 ... 264-1float ja 4 1,4 * 10-45 ... 3,4 * 1038

double ja 8 5,0 * 10-324 ... 1,7 * 10308

decimal ja 16 1,0 * 10-28 ... 7,9 * 1028

char ja 2 Unicode-Zeichen 0 ... 65536bool ja 1 true | falsestring ja Ref max. ca. 231 Unicode-Zeichenobject ja Ref kann jeden anderen Typ enthalten

• CLS (Common Language Specifikation) Kompatibilität: Datentypen werden von allen .NET-Sprachen verwendet

Beispiel 2.2

static void Main(string[] args){

Console.WriteLine("{0}", (float)10.0-(float)9.9); // 0,1000004Console.WriteLine("{0}", (double)10.0-(double)9.9); // 0,0999999999999996Console.WriteLine("{0}", (decimal)10.0-(decimal)9.9); // 0,1

}

Page 12: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 12 -

2.3 Variablendeklarationen und Zuweisungen für elementare Datentypen

Syntax

variable-declaration

name =

,

;expressiontype

• Variablen können nur innerhalb von Methoden- und Anweisungsblöcken deklariert werden

• Der Gültigkeitsbereich einer (lokalen) Variablen ist der Block, in dem die Deklaration erfolgt.

• Eine (lokale) Variable wird nicht automatisch initialisiert und verfügt folglich über keinen Standardwert.

Syntax

value-assign

name = ;expression

• die Verwendung einer nicht instantiierten Variablen führt zu Compilerfehler

Beispielint i = 0;Console.WriteLine(i);

int j;Console.WriteLine(j);

Page 13: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 13 -

2.4 Konstantendeklarationen für elementare Datentypen

Syntax

constant-declaration

name =

,

;expressiontypeconst

• expression ist ein Konstantenausdruck

Beispielint j = 4;const int i = 3 + j;

2.5 Werte- und Referenztypen

• Wertetypen

− Variablen vom Wertetyp speichern ihre Daten im Stack

− Wertetypen: alle einfachen Datentypen, dazu Stukturen (struct) und Aufzählungen (enum) als nutzerdefinierte Datentypen

• Referenztypen

− Variablen vom Referenztyp enthalten Verweise (Zeiger) auf ihre Daten im Heap

− Variablen vom Referenztyp selbst werden im Stack oder im Heap gespeichert

− Referenztypen: object und string, dazu Arrays (array), Klassen (class), Schnittstellen (interface) und Delegaten (delegate) als nutzerdefinierte Datentypen

− es existiert keine "Referenzarithmetik"

Page 14: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 14 -

2.6 Variablendeklarationen und Zuweisungen für Referenztypen

Syntax

variable-declaration

name =

,

;type new constructor

• ein (Standard-)Konstruktor hat die Form: <type>( )

• eine Referenzvariable muß vor ihrer Verwendung instanziiert werden

Syntax

variable-instanciation

name = ;new constructor

• Besonderheiten

− string- und object-Variablen brauchen nicht instanziiert zu werden

− struct-Variablen können instanziiert werden

Beispiel 2.6.a

namespace Beispiel{

struct MyStruct{

public int x;public int y;

}class MyClass{

Page 15: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 15 -

public int v;public int w;

}class Program{

static void Main(string[] args){

int i = 3;

string s = "Hallo";object o = 17;

MyStruct t;t.x=6;

MyClass c1 = new MyClass();c1.w = 8;

MyClass c2 = c1;}

}}

2.7 Boxing und Unboxing

Beispiel

class MyClass{

public int v;public int w;

}. . .MyClass c1 = new MyClass();c1.w = 8;Console.WriteLine("{0}", c1.w);MyClass c2 = c1;Console.WriteLine("{0} {1}", c1.w, c2.w);c2.w = 3;Console.WriteLine("{0} {1}", c1.w, c2.w);

Beispiel

object o1 = new object(); // auch object o1;o1=8;Console.WriteLine("{0}",o1);object o2=o1;Console.WriteLine("{0} {1}",o1,o2);o2=3;Console.WriteLine("{0} {1}",o1,o2);

Page 16: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 16 -

• Boxing

Implizite Konvertierung eines Wertetyps in den Typ Object durch die .NET-Laufzeitumgebung bei der Zuweisung eines Wertes an eine Objekt-Referenz

<object-variable> = <value-variable>

• intern wird Speicherplatz in Heap allokiert und der Wert der Wertevariable dort abgelegt (Kopie)

• Unboxing

Explizite Konvertierung eines Objekttyps in einen Wertetyp

<value-variable> = ( <value-type> ) <object-variable>

• Wertetyp muß mit dem Typ der Wertevariablen entsprechend Konvertierungsregeln übereinstimmen

• .NET-Laufzeitsystem kopiert Wert, den die object-variable referenziert, in werte-variable

• auch Methode Convert.To<value-type>( <object-variable> ) möglich

Beispiel

object o = 1; // Boxingint i = (int) o; // Unboxingint i = Convert.ToInt32(o); // Unboxing

Page 17: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 17 -

3 Konsolen-Eingabe und -Ausgabe

• Ein-/Ausgabemethoden der Klasse Console definiert im namespace System:

− Console.WriteLine

− Console.Write

− Console.ReadLine

− Console.Read

3.1 Formatierte Ausgabe

• Deklarationen in der Klasse Console:

public static void WriteLine (string format, params Object[] arg)public static void Write (string format, params Object[] arg)

• geben Werte der Argumente entsprechend der Formatzeichenkette aus

• WriteLine schließt Ausgabe mit '\n' ab, Write nicht

• für WriteLine und Write existieren weitere, nicht CLS-compatible Überladungen der Methoden

Syntax

<formatierte ausgabe> ::=Console.WriteLine ( " <zeichenfolge> " [, <ausdruck> ]... )Console.Write ( " <zeichenfolge> " [, <ausdruck> ]... )

<zeichenfolge> ::=<zeichen > [ <zeichenfolge> ]...

| <formatausdruck> [ <zeichenfolge> ]...

<formatausdruck> ::={ <n> [ , <m> ] [ : <format> ] }

• <n>: nullbasierter Zähler für Ausdrucksliste

• <m>: Breite der Ausgabe des n-ten Ausdrucks

<format> ::=

D - Anzeige als Integer | E - Anzeige in Exponentialschreibweise | F - Anzeige im Festpunktformat | X - Anzeige Hexadezimal | C - Anzeige im lokalenWährungsformat | ...

Page 18: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 18 -

• Ausgabe von Escape-Zeichen möglich: \n, \t, ...

Beispiel

Console.WriteLine("Hello World!");

string s1 = "Hello";string s2 = "World";Console.WriteLine("{0} {1}!", s1, s2);

double d = 3.14;int i = 5;Console.WriteLine("i={1} d={0}", d, i);

Console.WriteLine("d={0,15:F}\nd={0,15:E}", d);

3.2 Werteeingabe

Zeichenketteneingabe

• Deklaration in der Klasse Console

public static string Console.ReadLine( )

• liest ein oder mehrere Zeichen aus dem Eingabestrom (Tastatur)

• liefert Zeichenkette zurück

• Eingabe endet nach Einlesen von \n, \n nicht Bestandteil der Zeichenkette

Beispiel

static void Main(string[] args){

string s;s = Console.ReadLine();Console.WriteLine("{0}", s);

}

• für jeden einfachen Datentyp existiert überladene Methode zur Konvertierung eines String in einen Datentyp:

public static <datentyp>Parse( <string> )

Page 19: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 19 -

Beispiel

static void Main(string[] args){

int i;i = Int32.Parse(Console.ReadLine());Console.WriteLine("{0}", i + 3);

double d; d = Double.Parse(Console.ReadLine());

Console.WriteLine("{0:E}", d);

}

Zeicheneingabe

• Deklaration in der Klasse Console

public static int Console.Read( )

• liest ein Zeichen aus Eingabestrom und gibt dessen ASCII-Code als int zurück

• liest, solange noch Zeichen im Eingabestrom vorhanden

Beispiel

static void Main(string[] args){

int i;i = Console.Read(); Console.WriteLine("{0}", i);

i = Console.Read();Console.WriteLine("{0}", i); Console.ReadLine();i = Console.Read();Console.WriteLine("{0}", i);

}

Page 20: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 20 -

4. Operatoren

Primär x.y -> f(x) a[x] x++ x-- new typeof checked uncheckedUnär + - ! ~ ++x --x (type)xArithmetisch * / % + -Verschiebung << >>Relational und Typtest < > <= >= is asGleichheit == !=Logisch & ^ |Bedingt && || ?:Zuweisung = += -= *= /= %= &= |= ^= <<= >>= =>

• alle Operatoren aus C++ auch in C# verfügbar

• neue Operatoren: typeof, checked/unchecked, is/as und =>

typeof-Operator

Liefert das System.Type-Objekt für einen Datentyp.

is/as-Operator

Der is-Operator überprüft, ob ein Objekt mit einem bestimmten Typ kompatibel ist. Der as-Operator wird verwendet, um Konvertierungen zwischen kompatiblen Typen auszuführen.

=> Operator

Lambda-Operator

Page 21: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 21 -

checked/unchecked-Operator

Syntax

<checked-statement> ::=

checked <block>

• aktiviert explizit die Überlaufprüfung für arithmetische Operationen und Konvertierungen mit ganzzahligen Typen innerhalb des Anweisungsblockes

Syntax

<unchecked-statement> ::=

unchecked <block>

• unterdrückt explizit die Überlaufprüfung für arithmetische Operationen und Konvertierungen mit ganzzahligen Typen innerhalb des Anweisungsblockes

Beispiel

static void Main(string[] args){

int i=2147483647; // Bereich int (Int32): -2 147 483 648 ... 2 147 483 647int j=1;checked{

Console.WriteLine("{0}",i+j);}

}

Beispiel

static void Main(string[] args){

int i=2147483647; // Bereich int (Int32): -2 147 483 648 ... 2 147 483 647int j=1;unchecked{

Console.WriteLine("{0}",i+j);}

}

Page 22: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 22 -

5. Anweisungen

• alle Steueranweisungen aus C++ auch in C# verfügbar

− if-statement

− switch-statement

− while-statement

− do-while-statement

− for-statement

• neue Anweisungen in C#:

foreach-statement

Syntax

foreach-declaration

foreach name( type )arrays-name blockin

• für jedes array-Element wird der Anweisungsblock ausgeführt

• Zugriff auf die Elemente durch variable

Beispiel

int[] arr = {1,2,3,4,5};foreach (int i in arr)

Console.WriteLine("{0}", i);

try/catch/finally-statement

dient der Ausnahmebehandlung (Exceptions)

throw-statement

explizites Werfen von Ausnahmen in einer Anwendung

Page 23: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 23 -

using-statement

Impliziter Aufruf des Garbage Collectors zum Freigeben von Objekten

Modifikation switch-statement

• Regel: enthält ein case-Zweig eine Anweisung, dann muß er mit einer Sprunganweisung (break oder goto) abschließen

Beispiel (in C++ zulässig)

int _tmain(int argc, _TCHAR* argv[]){

char c='A';switch(c){case 'A': case 'B':printf("A oder B");case 'C': printf("C");break;default:printf("D");}return 0;

}

Besipiel (in C# nicht zulässig)

static void Main(string[] args){

char c='A';switch(c){

case 'A': case 'B':

Console.WriteLine("A oder B");case 'C':

Console.WriteLine("C");break;

default:Console.WriteLine("D");

}}

Page 24: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 24 -

Beispiel

static void Main(string[] args){

char c='A';switch(c){

case 'A': case 'B':

Console.WriteLine("A oder B");break;

case 'C': Console.WriteLine("C");break;

default:Console.WriteLine("D");break;

}}

• neben break weitere Sprunganweisung: goto

Syntax

<goto-statement> ::=

goto case <const-expression>

Beispiel

static void Main(string[] args){

char c='A';switch(c){

case 'A': Console.Write("A");goto case 'B';

case 'B':Console.Write("B");goto case 'C';

case 'C': Console.Write("C");break;

}}

Page 25: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 25 -

6 Komplexe Wertetypen

6.1 Aufzählungen

• Ein Enumeration-Typ deklariert eine Reihe von benannten Konstanten

Syntax

enum-declaration

enum-modifier enum name

{ }

enum-modifier

type:

name =

,

expression

access-modifier

• Variablen eines Enumeration-Typs können die in der Aufzählungsliste definierten Konstanten-Werte annehmen

• alle Konstanten-Werte sind vom Basistyp, der nur ein ganzzahliger Typ sein kann (byte ... ulong). Default: int

• wird kein Wert explizit zugewiesen, erhalten die Konstanten aufsteigend von 0 beginnend int-Werte

• Enumeration-Deklarationen sind nur innerhalb von Namespace-Deklarationen, Klassen-Deklarationen und Struktur-Deklarationen zulässig.

• Außerhalb einer Klassen- oder Struktur-Dekaration ist als Zugriffsmodifizierer nur public oder internal zulässig. Default: internal

Page 26: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 26 -

• Innerhalb einer Struktur-Deklaration (Strukturmember) sind nur die Zugriffsmodifizierer public, internal oder private erlaubt. Default: private

• Innerhalb einer Klassen-Deklaration (Klassenmember) sind alle Zugriffsmodifizierer erlaubt. Default: private

Beispiel 6.1.a

namespace Beispiel{

class Program{

public enum Geld : byte{

einer = 1,zweier, // implizit 2fünfer = 5,zehner = 2 * fünfer,fünfziger = 5 * zehner

}static void Main(string[] args){

int meinGeld = (int)Geld.zehner + 2 * (int)Geld.fünfziger;Console.WriteLine("{0}", meinGeld);

}}

}

• die Werte eines Enumeration-Typs sind nicht auf die Werte der Konstanten beschränkt

Page 27: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 27 -

6.2 Strukturen

6.2.1 Strukturdeklaration

Syntax

struct-declaration

struct-modifier struct name {

struct-member

}

struct-modifier struct-member

constant-field-declaration

field-declarationaccess-modifier

struct-declaration

• beginnt mit Schlüsselwort struct gefolgt von einem Strukturtyp-Namen und einem Block mit den Strukturelementen

• Struktur-Deklarationen sind nur innerhalb von Namespace-Deklarationen, Klassen-Deklarationen und Struktur-Deklarationen zulässig.

• Außerhalb einer Klassen- oder Struktur-Dekaration ist als Zugriffsmodifizierer nur public oder internal zulässig. Default: internal

• Innerhalb einer Klassen-Deklaration (Klassenmember) sind alle Zugriffsmodifizierer erlaubt. Default: private

• Innerhalb einer Struktur-Deklaration (Strukturmember) sind nur die Zugriffsmodifizierer public, internal oder private erlaubt. Default: private

Page 28: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 28 -

• Variablen-Felder können in Strukturen nicht initialisiert werden

Beispiel 6.2.1.a

namespace Beispiel{

public struct Person{

public string name;public int alter;public struct Adresse{

public string ort;public string strasse;

}public Adresse anschrift;

} class Program { static void Main(string[] args) {

Person student;student.name="Meier";student.alter=25;student.anschrift.ort="HST";student.anschrift.strasse="Hafenweg";Console.WriteLine("{0}, {1}, {2}, {3}",student.name, student.alter,

student.anschrift.ort, student.anschrift.strasse);}

}}

6.2.2 Methoden als Strukturmember (encapsulation)

• Kapselung: Verfahren, bei dem Daten und Funktionalität von Objekten zu einem Typ zusammengefaßt werden.

komplexer Datentyp (struct) ⇒ abstrakter Datentyp (class)

Beispiel 6.2.2.a

namespace Beispiel{

class Program{

static void Main(string[] args){

int zaehler1 = 1;int nenner1 = 2;int zaehler2 = 2;

Page 29: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 29 -

int nenner2 = 3;int zaehler3;int nenner3;zaehler3 = zaehler1 * nenner2 + zaehler2 * nenner1;nenner3 = nenner1 * nenner2;Console.WriteLine("{0}/{1}", zaehler3, nenner3);

}}

}

Beispiel 6.2.2.b

namespace Beispiel{

class Program{

struct Bruch{

public int zaehler;public int nenner;

}static Bruch Init(int z, int n){

Bruch b;b.zaehler = z;b.nenner = n;return b;

}static Bruch Addiere(Bruch b1, Bruch b2){

Bruch b;b.zaehler = b1.zaehler * b2.nenner + b2.zaehler * b1.nenner;b.nenner = b1.nenner * b2.nenner;return b;

}static void Main(string[] args){

Bruch bruch1 = Init(1,2);Bruch bruch2 = Init(2,3);Bruch bruch3;bruch3=Addiere(bruch1, bruch2);Console.WriteLine("{0}/{1}", bruch3.zaehler, bruch3.nenner);

}}

}

Page 30: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 30 -

• Ein abstrakter Datentyp ist eine Struktur/Klasse, deren Komponenten

− Daten und

− Funktionen, die auf die Datenkomponenten zugreifen

sind.

• gekapselte Funktionen heißen Methoden

Syntax

struct-member

constant-field-declaration

field-declaration

struct-declaration

method-declaration

Beispiel 6.2.2.c

namespace Beispiel{

class Program{

struct Bruch{

public int zaehler;public int nenner;public void Init(int z, int n){

zaehler = z;nenner = n;

}public Bruch Addiere(Bruch b2){

Bruch b;b.zaehler = zaehler * b2.nenner + b2.zaehler * nenner;b.nenner = nenner * b2.nenner;return b;

}}static void Main(string[] args){

Bruch bruch1 = new Bruch();

Page 31: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 31 -

Bruch bruch2 = new Bruch();Bruch bruch3 = new Bruch();

bruch1.Init(1, 2);bruch2.Init(2, 3);bruch3 = bruch1.Addiere(bruch2);Console.WriteLine("{0}/{1}", bruch3.zaehler, bruch3.nenner);

}}

}

• Strukturen sollten nur dann verwendet werden, wenn deren Komplexität gering ist

6.2.3 Einfache Typen als Strukturen

• zu jedem einfachen Datentyp ist in C# eine Struktur deklariert. Ausnahme: für string und object sind Klassen deklariert

Datentyp Strukturbyte Bytesbyte SByteshort Int16ushort UInt16int Int32uint UInt32long Int64ulong UInt64float Singledouble Doubledecimal Decimalchar Charbool BooleanDatentyp Klassestring Stringobject Object

• Auf die Member dieser Strukturen (Methode, Eigenschaften) können Anwendungsprogramme zugreifen

Beispiel

char c = 'a';Console.WriteLine("{0} {1}", c, Char.ToUpper(c)); // Ausgabe: a A

MyStruct structObject = new MyStruct();Console.WriteLine("{0}", structObject.GetType()); // Ausgabe: Beispiel.Program+MyStruct

• Datentypen und zugehörige Strukturen können gleichberechtigt verwendet werden

Page 32: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 32 -

7 Klassen und Klassenmember

• allgemeine Merkmale von Objekten

− Zustände

− Fähigkeiten, zu agieren

− Fähigkeit, zu reagieren

• Eine Klasse ist ein Datentyp (Datenstruktur), in der Zustände als Felder und Fähigkeiten als Methoden gekapselt werden.

• Die Felder und Methoden einer Klasse bezeichnet man als Member

• Ein Objekt ist eine dynamisch erstellte Instanz einer Klasse

7.1 Einführung UML: Klassen

• Softwareentwicklungsprozeß

− Anforderungsanalyse

− Entwuf

− Implementierung

Unified Modelling Language

• UML

− Standardisierte Sprache zur Modellierung von Software- und anderen Systemen

− Definiert die dafür erforderlichen Begriffe und Begiffsbeziehungen

• entwickelt von der Object Management Group (OMG), Standard seit 1998

• Modellelemente der UML

− Anwendungsfalldiagramm

− Klassendiagramm

− Aktivitätsdiagramm

− Kollaborationsdiagramm

− Sequenzdiagramm

− Zustandsdiagramm

− Komponentendiagramm

− Einsatzdiagramm

Page 33: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 33 -

• Klassendiagramm

Grafische Darstellung von Klassen und deren Beziehungen untereinander zur (statischen) Modellierung objektorientierter Softwaresysteme

UML: Klassen

• Klassen bestehen aus Membern:

− Felder (auch Datenmember, Eigenschaften, Attribute, Datenelemente, Instanzvariablen ...)

− Methoden (auch Operationen, Prozeduren, Routinen, Funktionen, Services, ...)

klassenname

felder

methoden

oder

klassenname

felder oder

klassenname

methoden

• klassenname

− Name der Klasse im Singular

− Darstellung in PascalConvention: beginnt mit Großbuchstaben

• felder

− Folge von Feldbeschreibungen der Form

modifizierer feldname : typ = initialwert { eigenschaft }

− feldname in camelConvention: beginnt mit Kleinbuchstaben

− mögliche modifizierer:

+ für public- für private# für protected

/ für abgeleitetes (berechnetes) Feld

− eigenschaft ist zusätzliche Eigenschaft, z.B. {ReadOnly}

− alle Bestandteile außer feldname sind optional

Page 34: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 34 -

• methoden

− Folge von Methodenbeschreibungen der Form

modifizierer methodenname ( argumentliste ) : rückgabetyp { eigenschaft }

− modifizierer wie bei Feldern außer /

− argumentliste ist kommagetrennte Folge von Argumentbeschreibungen:

richtung argumentname : typ = initialwert

− richtung: in-, out- oder inout-Parameter

− methodenname in PascalConvention: beginnt mit Großbuchstaben

− alle Bestandteile außer methodenname sind optional

• Notizen

− Anmerkungen zu Klassen, Feldern oder Methoden

− als Rechteck mit Eselsohr dargestellt

Beispiel

Konto

- kontonr : int {ReadOnly}- inhaber : String- kontostand : float = 0,0

+ InhaberÄndern ( inhaber : string ) : void+ Einzahlung ( betrag : float ) : void+ Auszahlung ( betrag : float ) : void+ Kontostand ( ) : float+ Kontendaten ( out kontonr : int, out inhaber : String ): void

Kontoinhaber sollvolljährig sein

Page 35: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 35 -

7.2 Klassendeklaration

Syntax

class-declaration

class-modifier class name

{

class-member

}

class-modifier

class-base:

static

sealed

abstract

partialaccess-modifier

• class-base

Basis-Klasse oder (-Interface), von der die Klasse abgeleitet ist

• access-modifier

− eine außerhalb einer Klasse deklarierte Klasse kann nur die Zugriffsmodifizierer public oder internal besitzen

− sonst: alle

• weitere class-modifier:

abstractDefinition einer abstrakten Klasse, keine Klassenobjekte erzeugt

staticDefinition einer statischen Klasse, nur einmal pro Klasse initialisiert

sealed Definition einer versiegelten Klasse, nicht abgeleitet

partialüber mehrere Dateien verteilt definierte Klasse

Page 36: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 36 -

Syntax (Fortsetzung)

class-member

constant-field-declaration

field-declaration

method-declaration

property-declaration

event-declaration

indexer-declaration

operator-declaration

constructor-declaration

destructor-declaration

static-constructor-declaration

type-declaration

enum-declaration

struct-declaration

class-declaration

interface-declaration

delegate-declaration

type-declaration

• Klassenmember:

Felderimplementieren den statischen Zustand eines Klassenobjektes

Methodenimplementieren die Funktionalität von Klassenobjektenspezielle Methoden:

− Konstruktoren und Destruktoren

− Eigenschaften

− Indexer

− (überladene) Operatoren

− Ereignisse

Page 37: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 37 -

• Klassenobjekte werden generell durch Aufruf eines Konstruktors mit dem new-Operator erzeugt (instanziiert) und die Referenz auf den Speicher einer Variablen zugewiesen

class-name variable;variable = new class-name();oder

class-name variable = new class-name();

• jede deklarierte Klasse erhält vom System einen Standardkonstruktor class-name(), der nach Aufruf alle Klassenfelder initialisiert

• der Zugriff auf Klassenmember von außerhalb einer Klasse erfolgt durch Punktnotation

variable.member

7.3 Felder

• Felder sind Variablen- oder Konstantendeklarationen innerhalb von Klassen

Syntax

field-declaration

variable-declaration

static

volatile

readonly arrays-declarationaccess-modifier

• access-modifier

public, protected, private, internal, protected internal

• static

Statische Felder sind nicht Teil einer bestimmten Instanz, sondern existieren für eine Klasse nur einmal

• readonly

Schreibgeschützte Felder

• volatile

Flüchtige Felder

Beispiel 7.3.a

Page 38: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 38 -

namespace Beispiel{

class ValueSet{

public int count;public int[] values=new int[100];

}class Program{

static void Main(string[] args){

ValueSet vs = new ValueSet();vs.values[0]=33;vs.count++;vs.values[1]=-6;vs.count++;for(int i=0; i<vs.count; i++)

Console.WriteLine("{0}", vs.values[i]);}

}}

Syntax

constant-field-declaration

constant-declaration

access-modifier

Page 39: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 39 -

7.4 Methoden

7.4.1 Methodendeklaration

Syntax

method-declaration

method-modifier

void

name

{

constant-declaration

}

method-modifier

parameter(

static

virtual

sealed

new

override

abstract

extern

type )

variable-declaration

arrays-declaration

;

block

block

access-modifier

statement

Page 40: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 40 -

• der Methodenblock (-rumpf) enthält ausschließlich Konstanten-, Variablen- und Arraydeklarationen sowie Anweisungen, also weder Feld- noch weitere Methoden- oder Typdeklarationen

• new

explizites Verdecken der Methode einer Basisklasse durch eine gleichnamige Methode einer abgeleiteten Klasse

• sealed

versiegelte Methode, verhindert ein erneutes Überschreiben der Methode durch eine abgeleitete Klasse

• abstract

abstrakte Methode, besitzt keinen Methodenrumpf und muß in einer abgeleiteten Klasse implementiert werden

• static

statische Methode, bezieht sich nicht auf ein Klassenobjekt, sondern auf die Klasse als Ganzes

• virtual

virtuelle Methode, bei der beim Aufruf der Laufzeittyp der Instanz, für die der Aufruf ausgeführt wird, die tatsächlich aufzurufende Methodenimplementierung bestimmt.

• extern

Externe Methode, wird extern implementiert (meist eine andere Sprache als C#)

• Regeln

− new und override dürfen nicht zusammen auftreten

− abstract und extern dürfen nicht zusammen auftreten

− abstract und extern haben ; statt block {}

− private darf nicht zusammen mit virtual, override oder abstract auftreten

Beispiel 7.4.1.a

namespace Beispiel{

class ValueSet{

public int count;public int[] values = new int[100];public void PrintValues(){

for (int i = 0; i < count; i++)Console.Write("{0} ", values[i]);

Console.WriteLine();}

}class Program{

Page 41: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 41 -

static void Main(string[] args){

ValueSet vs = new ValueSet();vs.values[0] = 33;vs.count++;vs.values[1] = -6;vs.count++;vs.PrintValues();

}}

}

7.4.2 Parameter einer Methode

Syntax (Fortsetzung)

parameter

type name

ref

out

,

params type name[ ]

• void als Parameter existiert nicht

Werteparameter

• Parameterübergabe call-by-value: Initialisierung des Parameters durch

datentyp variablen-name = ausdruck und damit Übergabe einer Kopie des Parameterwertes an den Methodenrumpf

Beispiel 7.4.2.a

namespace Beispiel{

class ValueSet{

public int count;public int[] values = new int[100];public void PrintValues() {. . .}

public bool AddValue(int value)

Page 42: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 42 -

{for(int i=0; i<count; i++)

if(values[i]==value) return false;values[count]=value;count++;return true;

}}class Program{

static void Main(string[] args){

ValueSet vs = new ValueSet();vs.AddValue(33);vs.AddValue(-6);vs.AddValue(15);vs.PrintValues();

}}

}

Beispiel

static void Main(string[] args){

ValueSet vs = new ValueSet();vs.AddValue(33);vs.AddValue(-6);vs.AddValue(15);vs.values[vs.count++]=33;vs.PrintValues();

}

Beispiel

class ValueSet{

private int count;private int[] values = new int[100];public bool AddValue(int value) {. . .}public void PrintValues() {. . .}

}

• eine korrekte Klassendefinition verbirgt ihre Felder nach außen

Page 43: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 43 -

Referenzparameter

Beispiel

class MyClass{

public void MyMethod(int i, string s){s = "World";i = 7;}

}class Program{

static void Main(string[] args){MyClass C = new MyClass();string z = "Hello";int j = 3; Console.WriteLine("{0} {1}", z, j); // Ausgabe: 'Hello 3C.MyMethod(j, z);Console.WriteLine("{0} {1}", z, j); // Ausgabe: 'Hello 3}

}

• call-by-value wirkt auf Werteobjekte und String-Referenzobjekte in der gleichen Weise

• Parameterübergabe call-by-reference: Initialisierung des Parameters

ref datentyp variablen-name = variablen-name mit einer Objektreferenz

• alle mit ref als Referenzparameter definierten Parameter müssen mit ref aufgerufen werden

• als Parameter dürfen nur Variablen übergeben werden

• Variablen müssen aktuell ein Objekt referenzieren

Beispiel 7.4.2.b

namespace Beispiel{

class ValueSet{

private int count;private int[] values = new int[100];public void PrintValues() {. . .}

public bool AddValue(int value) {. . .}public bool NextGreaterValue(ref int value){

Page 44: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 44 -

if (count == 0) return false;int nextValue = 0;int i = 0;while (i < count) {

if (values[i] > value){

nextValue = values[i];break;

}i++;

}if (i == count) return false;while (i < count){

if ((values[i] > value) && (values[i] < nextValue))nextValue = values[i];

i++;}value = nextValue;return true;

}}class Program{

static void Main(string[] args){

ValueSet vs = new ValueSet();vs.AddValue(33);vs.AddValue(-6);vs.AddValue(15);vs.AddValue(-15);

int value = -15;while (vs.NextGreaterValue(ref value) == true)

Console.WriteLine("{0} ", value); // Ausgabe: -6 15 33}

}}

Beispiel

class MyClass{

public void MyMethod(ref int i, ref string s){

s = "World";i = 7;

}}class Program{

static void Main(string[] args){

MyClass C = new MyClass();

Page 45: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 45 -

string z = "Hello";int j = 3;Console.WriteLine("{0} {1}", z, j); // Ausgabe: 'Hello' 3C.MyMethod(ref j, ref z);Console.WriteLine("{0} {1}", z, j); // Ausgabe: 'World' 7

}}

• call-by-reference wirkt auf Werteobjekte und String-Referenzobjekte in der gleichen Weise

• bei Übergabe von Werteobjekten als Referenzparameter: Boxing

Out-Parameter

• Out-Parameter sind spezielle Referenzparameter, die bei der Übergabe an eine Methode noch kein Objekt referenzieren müssen

• Parameterübergabe call-by-reference: Initialisierung des Parameters

out datentyp variablen-name = variablen-name mit einer Objektreferenz

• alle mit out als Referenzparameter definierten Parameter müssen mit out aufgerufen werden

• als Parameter dürfen nur Variablen übergeben werden

Beispiel 7.4.2.c

namespace Beispiel{

class ValueSet{

private int count;private int[] values = new int[100];public void PrintValues() {. . .}

public bool AddValue(int value) {. . .}public bool NextGreaterValue(ref int value) {. . .}public bool GetMin(out int min){

min = 0;if (count == 0) return false;for (int i = 0; i < count; i++)

if (values[i] < min)min = values[i];

return true;}

}class Program

Page 46: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 46 -

{static void Main(string[] args){

ValueSet vs = new ValueSet();vs.AddValue(33);vs.AddValue(-6);vs.AddValue(15);vs.AddValue(-15);vs.PrintValues();

int minimum;if (vs.GetMin(out minimum) == true)

Console.WriteLine("{0} ", minimum);else

Console.WriteLine("Leere Menge");}

}}

Übergabe von Klassenobjekten

• Typen, die auf Klassendefinition basieren, sind Referenztypen

Beispiel

class MyClassA{

public string s = "Hello";public int i = 3;

}class MyClassB{

public void MyMethod(MyClassA obj){obj.s = "World";obj.i = 7;}

}class Program{

static void Main(string[] args){MyClassA objA = new MyClassA();MyClassB objB = new MyClassB();Console.WriteLine("{0} {1}", objA.s, objA.i);objB.MyMethod(objA);Console.WriteLine("{0} {1}", objA.s, objA.i);}

}

Page 47: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 47 -

Beispiel 7.4.2.d

namespace Beispiel{

class ValueSet{

private int count;private int[] values = new int[100];public void PrintValues() {. . .}

public bool AddValue(int value) {. . .}public bool NextGreaterValue(ref int value) {. . .}public bool GetMin(out int min) {. . .}public void Union(ValueSet v) {

int min;v.GetMin(out min);min--;while(v.NextGreaterValue(ref min)==true)

AddValue(min);}

}class Program{

static void Main(string[] args){

ValueSet vs1 = new ValueSet();vs1.AddValue(9); vs1.AddValue(7); vs1.AddValue(5); vs1.AddValue(-3);vs1.PrintValues();ValueSet vs2 = new ValueSet();vs2.AddValue(-5); vs2.AddValue(5); vs2.AddValue(3);vs2.PrintValues();vs1.Union(vs2);vs1.PrintValues(); // Ausgabe: 9 7 5 -3 -5 3

}}

}

Page 48: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 48 -

Parameterlisten

• params definiert ein beliebig langes Array von Parametern gleichen Datentyps

params arraytyp variablen-name

• Einschränkungen (siehe Syntax):

− nur ein params-Array in einer Parameterliste

− params-Array ist immer das letzte Element in einer Liste

− Referenzparameter als params-Array nicht erlaubt

Beispiel 7.4.2.e

namespace Beispiel{

class ValueSet{

private int count;private int[] values = new int[100];public void PrintValues() {. . .}

public bool AddValue(int value) {. . .}. . .

public bool AddValues(int cnt, params int[] val){

for (int i = 0; i < cnt; i++)for (int j = 0; j < count; j++)

if (values[j] == val[i]) return false;for (int i = 0; i < cnt; i++)

values[count++] = val[i];return true;

}}class Program{

static void Main(string[] args){

ValueSet vs = new ValueSet();vs.AddValue(33);vs.AddValue(-6);vs.AddValue(15);vs.AddValue(-15);vs.PrintValues();vs.AddValues(3, 7, 5, -3);vs.PrintValues(); // Ausgabe: 33 -6 15 -15 7 5 -3

}}

}

Page 49: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 49 -

Selbstreferenz

• Referenz this, mit der innerhalb einer Klasse auf die Klasse selbst verwiesen wird

• Zugriff auf Klassenmember innerhalb der Klasse durch

this. member-name

Beispiel

public bool AddValues(int count, params int[] values){

for (int i = 0; i < count; i++)for (int j = 0; j < this.count; j++)

if (this.values[j] == values[i]) return false;for (int i = 0; i < count; i++)

this.values[this.count++] = values[i];return true;

}

Beispiel

public bool AddValues(params int[] values){

foreach (int element in values)for (int j = 0; j < this.count; j++)

if (this.values[j] == element) return false;foreach (int element in values) // Elemente einfügen

this.values[this.count++] = element;return true;

}

Page 50: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 50 -

7.4.3 Rückgabewerte einer Methode

Objektreferenzen als Rückgabewert

Beispiel 7.4.3.a

namespace Beispiel{

class ValueSet{

private int count;private int[] values = new int[100];public void PrintValues() {. . .}public bool AddValues(params int[] values) {. . .}. . .public ValueSet IncAll(ValueSet v){

for (int i = 0; i < count; i++)values[i]++;

return v;}

}class Program{

static void Main(string[] args){

ValueSet vs = new ValueSet();vs.AddValues(9, 7, 5, -3);vs.PrintValues();

vs.IncAll(vs);vs.IncAll(vs);vs.PrintValues(); // Ausgabe: 11 9 7 -1

vs.IncAll(vs.IncAll(vs));vs.PrintValues(); // Ausgabe: 13 11 9 1

}}

}

Page 51: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 51 -

Selbstreferenz als Rückgabewert

Beispiel 7.4.3.b

namespace Beispiel{

class ValueSet{

private int count;private int[] values = new int[100];public void PrintValues() {. . .}public bool AddValues(params int[] values) {. . .}. . .public ValueSet IncAll(){

for (int i = 0; i < count; i++)values[i]++;

return this;}

}class Program{

static void Main(string[] args){

ValueSet vs = new ValueSet();vs.AddValues(4, 9, 7, 5, -3);vs.PrintValues();

vs.IncAll();vs.IncAll();vs.PrintValues();

vs.IncAll().IncAll();vs.PrintValues();

}}

}

Page 52: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 52 -

7.4.4 Überladen von Methoden

• Zwei Methoden heißen überladen, wenn sie den gleichen Namen besitzen und

− sich in Anzahl und/oder Typ ihrer Parameter unterscheiden oder

− wenn sich zwei typgleiche Parameter nur darin unterscheiden, daß der eine als Referenz- und der andere als Werteparameter deklariert ist

• Compiler und JITter unterscheiden verschiedene Versionen einer Methode anhand von Typ und Anzahl der Parameter

⇒ (Name, Typen (incl. Wert/Referenz), Anzahl) = Signatur einer Methode

Beispiel

vs.IncAll(vs) ruft public ValueSet IncAll(ValueSet v) aufvs.IncAll() ruft public ValueSet IncAl() auf

• besitzen mehrere überladene Methoden eine Parameterliste sowie mehrere Parameter des gleichen Typs, dann wird (soweit möglich) die Methode mit den meisten Parametern aufgerufen

Beispiel 7.4.4.a

namespace Beispiel{

class MyClass{

public void MyMethod(params int[] i){

Console.WriteLine("M1");}public void MyMethod(int a, params int[] i){

Console.WriteLine("M2");}public void MyMethod(int a, int b, params int[] i){

Console.WriteLine("M3");}public void MyMethod(int a, int b, int c, params int[] i){

Console.WriteLine("M4");}

}class Program{

static void Main(string[] args){

MyClass C = new MyClass();C.MyMethod(1,2); // Ausgabe M3

Page 53: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 53 -

C.MyMethod(1,2,3,4); // Ausgabe M4}

}}

Beispiel 7.4.4.b

namespace Beispiel{

class MyClass{

public void MyMethod(int i){

Console.WriteLine("M1");}public void MyMethod(ref int i){

Console.WriteLine("M2");}

}class Program{

static void Main(string[] args){

MyClass C = new MyClass();int i=1;C.MyMethod(i); // Ausgabe M1C.MyMethod(ref i); / Ausgabe M2

}}

}

• Wird als Aufrufparameter ein Typ verwendet, der nicht definiert ist, versucht der Compiler in den höherwertigen Typ zu konvertieren

Beispiel 7.4.4.c

namespace Beispiel{

class MyClass{

public void MyMethod(float f){

Console.WriteLine("M1");}public void MyMethod(double d){

Console.WriteLine("M2");}

}class Program{

static void Main(string[] args)

Page 54: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 54 -

{MyClass C = new MyClass();C.MyMethod(1); // Ausgabe M1C.MyMethod(1.1); // Ausgabe M2

}}

}

7.5 Konstruktoren

Beispiel

class ValueSet{

private int count;private int capacity;private int[] values; public void PrintValues() {. . .}public bool AddValues(params int[] values) {. . .}. . .

}class Program{

static void Main(string[] args){

ValueSet vs = new ValueSet();vs.AddValues(4, 9, 7, 5, -3);

}}

Beispiel 7.5.a

namespace Beispiel{

class ValueSet{

private int count;private int capacity;private int[] values;public void PrintValues() {. . .}public bool AddValues(params int[] values) {. . .}

public void Initialize(int capacity){

this.capacity = capacity;this.values = new int[capacity];

}

}class Program{

static void Main(string[] args){

Page 55: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 55 -

ValueSet vs = new ValueSet();vs.Initialize(50);vs.AddValues(4, 9, 7, 5, -3);vs.PrintValues();

}}

}

• Konstruktoren einer Klasse sind spezielle Methoden, die bei der Instanziierung der Klasse mit new aufgerufen werden und die Felder initialisieren

Konstruktordeklaration

Syntax

constructor-declaration

constructor-modifier name

constructor-modifier

public

protected

internal

prot. int.

private

argument

(

extern

)

block

base:

this

parameter( )

Page 56: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 56 -

• name: ein Konstruktor hat generell den gleichen Namen wie die Klasse

• :this/:base: Verkettung des Konstruktors mit einem andren Konstruktor der gleichen Klasse/der Basisklasse

• Konstruktoren geben keinen Wert zurück

Instanziierung von Klassenobjekten

• die Instanziierung einer Klasse erfolgt generell durch Aufruf eines Konstruktors:

object-reference = new constructor ;

• Instanziierungsprozeß:

1. Speicherallokation für das Objekt im Heap

2. Initialisierung der Felder mit Initialwerten (falls definiert), sonst mit 0, "" oder null

3. Aufruf des Konstruktors

• wurde kein Konstruktor explizit deklariert, erzeugt das System implizit einen parameterlosen Standardkonstruktor: class-name ( )

Beispiel 7.5.b

namespace Beispiel{

class ValueSet{

private int count;private int capacity;private int[] values;public ValueSet(int capacity){

this.capacity = capacity;this.values = new int[capacity];

}public void PrintValues() {. . .}public bool AddValues(params int[] values) {. . .}

. . .}class Program{

static void Main(string[] args){

ValueSet vs = new ValueSet(50);vs.AddValues(4, 9, 7, 5, -3);vs.PrintValues();

}}

}

• sobald ein Konstruktor definiert wurde, wird der implizite Standardkonstruktor nicht mehr erzeugt

Page 57: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 57 -

• Konstruktoren können überladen werden

Beispiel 7.5.c

namespace Beispiel{

class ValueSet{

private int count;private int capacity;private int[] values;public ValueSet(){

capacity = 100;values = new int[100];

}public ValueSet(int capacity) {. . .}

public void PrintValues() {. . .}public bool AddValues(params int[] values) {. . .}

. . .}class Program{

static void Main(string[] args){

ValueSet vs1 = new ValueSet(50);vs1.AddValues(4, 9, 7, 5, -3);vs1.PrintValues();ValueSet vs2 = new ValueSet();vs2.AddValues(6, 8, 1);vs2.PrintValues();

}}

}

Page 58: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 58 -

Konstruktorverkettung

Beispiel

public ValueSet(int capacity, params int[] values){

this.capacity = capacity;this.values = new int[capacity];this.AddValues(values);

}

• Über Referenz :this kann für einen Konstruktor die Funktionalität eines anderen, bereits definierter Konstruktors der gleichen Klasse aufgerufen werden

Beispiel 7.5.d

namespace Beispiel{

class ValueSet{

private int count;private int capacity;private int[] values;public ValueSet() {. . .}public ValueSet(int capacity) {. . .}public ValueSet(int capacity, params int[] values): this(capacity){

this.AddValues(values);}public void PrintValues() {. . .}public bool AddValues(params int[] values) {. . .}

. . .}

}class Program{

static void Main(string[] args){

ValueSet vs1 = new ValueSet(50);vs1.AddValues(4, 9, 7, 5, -3);vs1.PrintValues();ValueSet vs2 = new ValueSet();vs2.AddValues(6, 8, 1);vs2.PrintValues();ValueSet vs3 = new ValueSet(70, 2, 5, -8);vs3.PrintValues();

}}

}

Page 59: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 59 -

7.6 Destruktor und Garbage Collection

Garbage Collector

• Garbage Collector (GC): Prozess, der im Hintergrund einer Anwendung abläuft mit der Aufgabe:

Suche nach nichtreferenzierten Objekten im Heap und Freigabe des Speicherplatzes

• wird ausgeführt, wenn

− Anwendung zeitweilig keine Prozessorleistung in Anspruch nimmt oder

− Speicherrecourcen für die Anwendung einen Minimalwert unterschreiten

• Voraussetzungen für das Freigeben von Speicher für ein Objekt durch Garbage Collector

− Gültigkeitsbereich einer Objektreferenz wird verlassen (Block)

− Nullzuweisung: objekt-variable = null;

• Ablauf einer Garbage Collection

− GC ermittelt, ob Destruktoren für freizugebende Objekte definiert wurden

− wurde Destruktoren definiert, werden diese ausgeführt

− GC gibt allokierten Speicher im Heap frei

− GC Komprimiert den Heap

• explizite Ausführung des GC durch Aufruf der statischen Methode GC.Collect() möglich

Destruktordefinition

• Destruktor: spezielle Methode, die durch den Garbage Collector aufgerufen wird

Syntax

destructor-declaration

name

extern

block( )~

• in C# kann der Destruktor für ein Objekt nicht explizit in einer Anweisung zur Ausführung gebracht werden

Page 60: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 60 -

• Destruktor sollte nur bei echter Notwendigkeit implementiert werden

Beispiel 7.6.a

namespace Beispiel{

class MyClass{

public MyClass(){

Console.WriteLine("DB-Connect");}~MyClass(){

Console.WriteLine("DB-Disconnect");}

}class Program{

static void Main(string[] args){

MyClass myObject = new MyClass();myObject = null;GC.Collect();Console.Read();Console.WriteLine("Main beendet");

}}

using-Anweisung

• Impliziter Aufruf des Garbage Collectors zum Freigeben von Objekten

Syntax

using-declaration

using )variable-declaration block(

,

• bei auftretenden Ausnahmen (Fehlern) oder nach Verlassen des Anweisungsblockes:

1. Aufruf einer Methode Dispose() 2. Ausführung des Garbage Collector für die instanziierten Objekte

• Voraussetzungen zur Verwendung von using: die Klasse, für die Objekte instanziiert wurden, muß:

− vom Interface IDisposable abgeleitet sein

Page 61: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 61 -

− die Methode Dispose() implementieren

Beispiel 7.6.b

class MyClass : IDisposable{

public MyClass(){

Console.WriteLine("DB-Connect");}void IDisposable.Dispose(){

Console.WriteLine("DB-Disconnect");}

}class Program{

static void Main(string[] args){

using (MyClass myObject = new MyClass()){

Console.WriteLine("myObject wird verwendent");}Console.WriteLine("Main beendet");

}}

Page 62: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 62 -

7.7 Eigenschaften

Beispiel 7.7.a

namespace Beispiel{

class ValueSet{

private int count;private int capacity;private int[] values;public ValueSet(int capacity) {. . .}public void PrintValues() {. . .}public bool AddValues(params int[] values) {. . .}public bool SetCapacity(int newCapacity){

if(newCapacity<this.count) return false;int[] tmpValues = new int[newCapacity];for(int i=0; i < this.count; i++)

tmpValues[i] = this.values[i];this.values = tmpValues;this.capacity = newCapacity;return true;

}

public int GetCapacity(){

return capacity;}

}class Program{

static void Main(string[] args){

ValueSet vs = new ValueSet(50);vs.AddValues(4, 9, 7, 5, -3);vs.PrintValues();Console.WriteLine("Kapazität: {0}",vs.GetCapacity());vs.SetCapacity(20);vs.PrintValues();Console.WriteLine("Kapazität: {0}",vs.GetCapacity());

}}

}

• Eine Eigenschaft (property) ist eine spezielle Methode, die es erlaubt, mittels Zuweisungsoperator auf private Felder von Klassen zuzugreifen

Page 63: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 63 -

Eigenschaftsdeklaration

Syntax

property-declaration

property-modifier name

property-modifier

get-accessor{type }

method-modifier

get/set-accessor

set-accessor

get-accessor set-accessor

set

get block

• sind die Modifikatoren abstract oder extern, dann besteht der Block nur aus dem Semikolon

• der Typ ist ist der Datentyp dieses Feldes, auf das zugegriffen wird

• der Eigenschaft-Name sollte der Name des Feldes, beginnend mit einem Großbuchstaben sein

• der Block enthält Anweisungen zum lesenden/schreibenden Zugriff auf das privates Feld

• der get-Acessor muß eine return-anweisung enthalten

• Eigenschaftsaufruf

− Getter-Aufruf: objekt-variable . eigenschaft-name

− Setter-Aufruf: objekt-variable . eigenschaft-name = ausdruck

• der Setter-Block besitzt eine Variable value zur Übernahme des Wertes von ausdruck

Page 64: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 64 -

Beispiel 7.7.b

namespace Beispiel{

class ValueSet{

private int count;private int capacity;private int[] values;public ValueSet(int capacity) {. . .}public void PrintValues() {. . .}public bool AddValues(params int[] values) {. . .}public int Capacity{

get{

return this.capacity;}set{

if (value < this.count) Console.WriteLine("Fehler");

int[] tmpValues = new int[value];for (int i = 0; i < this.count; i++)tmpValues[i] = this.values[i];this.values = tmpValues;this.capacity = value;

}}

}class Program{

static void Main(string[] args){

ValueSet vs = new ValueSet(50);vs.AddValues(4, 9, 7, 5, -3);vs.PrintValues();Console.WriteLine("Kapazität: {0}", vs.Capacity);vs.Capacity = 20;vs.PrintValues();Console.WriteLine("Kapazität: {0}", vs.Capacity);

}}

}

Page 65: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 65 -

7.8 Partielle Klassen

• ist eine Klassendeklaration in mehrere Teile aufgeteilt (z.B. in mehreren Quelldateien), so muß jeder Teil einen partial-Modifizierer enthalten

• alle Teile müssen in demselben Namespace deklariert werden.

• Wenn eine partielle Klassendeklaration eine Zugriffsspezifikation enthält, muß diese mit allen anderen Teilen übereinstimmen, in denen ebenfalls eine Zugriffsspezifikation angegeben ist.

Beispiel 7.8.a

Datei Program1.csnamespace Beispiel{

partial class ValueSet{

private int count;private int capacity;private int[] values;public ValueSet(int capacity) {. . .}

}class Program{

static void Main(string[] args){. . .}

}}

Datei Program2.csnamespace Beispiel{

partial class ValueSet{

public int Capacity {. . .}public void PrintValues() {. . .}public bool AddValues(params int[] values) {. . .}

}}

Page 66: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 66 -

7.9 Statische Klassen und Klassenmember

Beispiel 7.9.a

namespace Beispiel{

class ValueSet{

private int count;private int capacity;private int[] values;private int numberOfObjects;public ValueSet(int capacity){

this.capacity = capacity;this.values = new int[capacity];this.numberOfObjects++;

}}class Program1{

static void Main(string[] args){

ValueSet vs1 = new ValueSet(50);ValueSet vs2 = new ValueSet(50);

}}

}

7.9.1 Statische Member

• statische Member (Modifizierer static) gehören nicht einzelnen Instanzen, sondern allen Instanzen einer Klasse gemeinsam

• statische Member können sein:

− statische Felder (Klassenfelder)

− statische Eigenschaften (Klasseneigenschaften)

− statische Methoden (Klassenmethoden)

• Klassenfelder/-eigenschaften:

sind für alle Objekte einer Klasse identisch

• Instanzfelder/-eigenschaften:

sind objektspezifisch

• Klassenmethoden:

bestimmen das Verhalten einer Klasse unabhängig von einem konkreten Objekt

Page 67: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 67 -

• Instanzmethoden:

Ausführung ist an ein konkretes Objekt gebunden

• Der Zugriff auf statische Member erfolgt außerhalb einer Klasse durch class-name . member

Beispiel 7.9.1.a

namespace Beispiel{

class ValueSet{

private int count;private int capacity;private int[] values;private static int numberOfObjects;public ValueSet(int capacity){

this.capacity = capacity;this.values = new int[capacity];numberOfObjects++;

}public int GetNumberOfObjects(){

return numberOfObjects;}

}class Program1{

static void Main(string[] args){

ValueSet vs1 = new ValueSet(50);Console.WriteLine("Anzahl der Objekte: {0}", vs1.GetNumberOfObjects());ValueSet vs2 = new ValueSet(50);Console.WriteLine("Anzahl der Objekte: {0}", vs1.GetNumberOfObjects());

}}

}

• Statische Member sind nicht über Selbstreferenz (this) zugreifbar

• Klassenfelder werden initialisiert, wenn die Klasse zum ersten Mal geladen wird

Page 68: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 68 -

7.9.2 Statische Methoden

• statische Methoden (Klassenmethoden) dienen der Bereitstellung von Funktionen, die nicht an bestimmte Instanzen der Klasse gebunden sind

Beispiel 7.9.2.a

namespace Beispiel{

class ValueSet{

private int count;private int capacity;private int[] values;private static int numberOfObjects;public ValueSet(int capacity){

this.capacity = capacity;this.values = new int[capacity];numberOfObjects++;

}public static int GetNumberOfObjects(){

return numberOfObjects;}

}class Program1{

static void Main(string[] args){

ValueSet vs1 = new ValueSet(50);Console.WriteLine("Anzahl der Objekte: {0}", ValueSet.GetNumberOfObjects());ValueSet vs2 = new ValueSet(50);Console.WriteLine("Anzahl der Objekte: {0}", ValueSet.GetNumberOfObjects());

}}

}

Statische Konstruktoren

Syntax

static-constructor-declaration

namestatic

extern

block( )

Page 69: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 69 -

• statische Konstruktoren werden vom System selbst vor der Erzeugung einer ersten Instanz bzw. vor dem Zugriff auf ein erstes statisches Feld aufgerufen

• dürfen weder Sichbarkeit-modifizierer noch Parameter besitzen

7.9.3 Statische Klassen

• statische Klassen dienen der Bereitstellung allgemeingültiger Funktionen

• Regeln für statische Klassen:

− dürfen nur statische Member mit public veröffentlichen

− dürfen keine Konstruktoren enthalten

− können nicht abgeleitet werden

Beispiel 7.9.3.a

namespace Beispiel{

static class MyMath{

public static int Fak(int zahl){

int erg = 1;while (zahl != 0)

erg = erg * zahl--;return erg;

}public static int Quer(int zahl){

int erg = 0;while (zahl != 0)

erg = erg + zahl--;return erg;

}}class Program{

static void Main(string[] args){

Console.WriteLine("{0} {1}", MyMath.Fak(4), MyMath.Quer(4));}

}}

Page 70: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 70 -

UML: Statische Klassen und -member

• statische Klassen bzw. Klassenmember können durch Unterstreichung kenntlich gemacht werden

Beispiel

ValueSet

- count : int- capacity : int- values : int[]- numberOfObjects : int

+ ValueSet( capacity : int ) : void+ GetNumberOfObjects( ) : int

Page 71: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 71 -

7.10 Generika

Beispiel 7.10.a

namespace Beispiel{

class ObjectValueSet{

private int count;private int capacity;private object[] values;public ObjectValueSet(int capacity){

this.capacity = capacity;this.values = new object[capacity];

}public void PrintValues(){

for (int i = 0; i < count; i++)Console.Write("{0} ", values[i]);

Console.WriteLine();}public bool AddValues(params object[] values){

foreach (object element in values)for (int j = 0; j < this.count; j++)

if (this.values[j] == element) return false;foreach (object element in values)

this.values[this.count++] = element;return true;

}}class Program1{

static void Main(string[] args){

ObjectValueSet vs1 = new ObjectValueSet(50);vs1.AddValues(4, 9, 7, 5, -3);vs1.PrintValues();ObjectValueSet vs2 = new ObjectValueSet(50);vs2.AddValues("Anna", "Hannes", "Willi", "Paul");vs2.PrintValues();

}}

}

Page 72: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 72 -

Beispiel 7.10.b

static void Main(string[] args){

ObjectValueSet vs = new ObjectValueSet(50);vs.AddValues(4, "Anna", 9.172, true);vs.PrintValues();

}

Beispiel 7.10.c

namespace Beispiel{

class ObjectValueSet{

private int count;private int capacity;private object[] values;public ObjectValueSet(int capacity) {. . .}public void PrintValues() {. . .}public bool AddValues(params object[] values) {. . .}public object GetValue(int index){

return values[index];}

}class Program1{

static void Main(string[] args){

ObjectValueSet vs = new ObjectValueSet(50);vs.AddValues(4, "Anna", 9.172, true);vs.PrintValues();int v;v = (int)vs.GetValue(0); // hier o.k.v = (int)vs.GetValue(1); // hier Laufzeitfehler

}}

}

• Nachteile der Lösung mit Datentyp object:

− Typprüfung kann nicht vom Compiler geleistet werden

− Boxing/Unboxing führt zu schlechter Performance

Page 73: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 73 -

7.10.1 Generische Klassen

• Generische Klassen sind Klassen, die Platzhalter für Datentypen besitzen, die erst zur Laufzeit konkretisiert werden (Typparameter)

• Erleichterung, da

− striktere Typprüfung zur Kompilierzeit möglich

− explizite Konvertierungen zwischen Datentypen seltener erforderlich

− keine Notwendigkeit von Boxingvorgängen und Typprüfungen zur Laufzeit

Syntax

generic-class-declaration

class-modifier class name

{

class-member

}

class-base:

type-parameter

,

< >

where type-parameter : condition

,

• Typparameter können innerhalb einer Generischen Klasse an jeder Stelle stehen, an denen ein Datentyp stehen kann

• bei der Instanziierung einer generischen Klasse wird jedem Typparameter in der Reihenfolge seines Auftretens ein konkreter Datentypen zugeordnet und damit jeder in der Klasse auftretende Typparameter durch den konkreten Datentyp ersetzt

Page 74: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 74 -

Syntax

generic-class-instance

name

= ;

class-type

new constructor

data-type

,

< >

parameter( )

constructor

class-type data-type

,

< >

Beispiel 7.10.1.a

namespace Beispiel{

class ValueSet<T>{

private int count;private int capacity;private T[] values;public ValueSet(int capacity){

this.capacity = capacity;this.values = new T[capacity];

}public void PrintValues() { . . . }public bool AddValues(params T[] values){

foreach (T element in values)for (int j = 0; j < this.count; j++)

if (this.values[j] == element) return false;foreach (T element in values)

this.values[this.count++] = element;return true;

}public void PrintValues() { . . . }

}class Program1{

Page 75: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 75 -

static void Main(string[] args){

ValueSet<int> vs1 = new ValueSet<int>(50);vs1.AddValues(3, 6, -5, 15);vs1.PrintValues();ValueSet<string> vs2 = new ValueSet<string>(50);vs2.AddValues("Anna", "Hannes", "Willi", "Paul");vs2.PrintValues();

}}

}

• Vergleichsoperatoren können nicht auf generische Typparameter angewendet werden

• die where-Klausel beschränkt die möglichen Ersetzungen eines Typparameters auf diejenigen Typen, die die condition erfüllen

• mögliche condition:

structclass

interface-name

Beispiel 7.10.1.b

namespace Beispiel{

class ValueSet<T> where T : IComparable{

private int count;private int capacity;private T[] values;public ValueSet(int capacity){

this.capacity = capacity;this.values = new T[capacity];

}public bool AddValues(params T[] values){

foreach (T element in values)for (int j = 0; j < this.count; j++)

if (element.CompareTo(this.values[j]) == 0) return false; foreach (T element in values)

this.values[this.count++] = element;return true;

}public void PrintValues() { . . . }

}class Program1{

static void Main(string[] args){

ValueSet<int> vs1 = new ValueSet<int>(8);vs1.AddValues(3, 6, -5, 15);

Page 76: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 76 -

vs1.PrintValues();ValueSet<string> vs2 = new ValueSet<string>(8);vs2.AddValues("Anna", "Hannes", "Willi", "Paul");vs2.PrintValues();

}}

}

7.10.2 Generische Methoden

• Generische Methoden sind Methoden, die Platzhalter (Typparameter) für Datentypen besitzen, die erst zur Laufzeit konkretisiert werden

Syntax

generic-method-declaration

method-modifier

void

name

parameter(

type

) block

type-parameter

,

< >

• Typparameter können sowohl Bestandteil der Parameterliste oder des Methodenrumpfs als auch der Rückgabetyp sein

• generische Methoden können Member generischer oder nicht-generischer Klassen sein

• es ist nicht erlaubt, in einer Methode den gleichen Typparameter zu definieren, wie in der Klasse

Beispiel 7.10.2.a

namespace Beispiel{

static class MyClass{

public static T Select<T>(T[] w){

Random rnd = new Random();T ret = w[rnd.Next(w.Length)];return ret;

}

Page 77: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 77 -

}class Program1{

static void Main(string[] args){

int[] f1 = new int[]{3,5,8,2};Console.WriteLine("Erg: {0}",MyClass.Select<int>(f1));string[] f2 = new string[]{"Anna","Hannes","Willi","Paul"};Console.WriteLine("Erg: {0}", MyClass.Select<string>(f2));

}}

• default ( typeparameter ) erzeugt

− 0 für übergebeneWertetypen

− NULL für übergebene Referenztypen

Beispiel 7.10.2.b

namespace Beispiel{

static class MyClass{

public static T Select<T>(T[] w){

if (w.Length == 0) return default(T);Random rnd = new Random();T ret = w[rnd.Next(w.Length)];return ret;

}}class Program1{

static void Main(string[] args){

int[] f1 = new int[] { 3, 5, 8, 2 };Console.WriteLine("Erg: {0}", MyClass.Select<int>(f1)); string[] f2 = new string[] {};Console.WriteLine("Erg: {0}", MyClass.Select<string>(f2));

}}

}

Page 78: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 78 -

7.11 Überladen von Operatoren

• Neben dem Überladen von Methoden ist in C# auch das Überladen von Operatoren durch den Programmierer möglich

• Überladene Operatoren sind öffentliche statische Methoden und müssen als Parameter das Objekt, auf das sie angewendet werden, besitzen

Syntax

operator-declaration

operator-modifier

unary operator

operator-modifier

public

type(

static

operator

extern

type

)name

binary operator type( )name , type name

unary operator

one of: + - ! ~ ++ true false

binary operator

one of: + - * / % & | ^ << >> == != > < >= <=

block

• Es darf nur die Funktionalität eines Operators geändert werden, nicht die Zahl der Operanden (unär/binär), die Priorität eines Operators bleibt unverändert

• es können keine neuen Operatoren definiert werden (z.B. ** für Exponentialoperator)

• es muß mindestens ein Argument (Operand) eines überladenen Operators ein Objekt der Klasse oder Struktur sein, in der der Operator definiert wurde

Page 79: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 79 -

• überladene Operatoren müssen einen Typ zurückgeben

• Überladene Operatoren können ihre Parameter nicht verändern

Unäre Operatoren

• die Operatoren ++ und -- müssen den Typ des Parameters zurückgeben

• die unären Operatoren +, -, ! und ~ können einen beliebigen Typ zurückgeben

Beispiel 7.11.a

namespace Beispiel{

class ValueSet{

private int capacity;private int count;private int[] values;public ValueSet(int capacity) { . . . }public void PrintValues() { . . . }public bool AddValues(params int[] values) { . . . }public static ValueSet operator ++(ValueSet v){

for (int i = 0; i < v.count; i++)v.values[i]++;

return v;}

}class Program{

static void Main(string[] args){

ValueSet vs = new ValueSet(10);vs.AddValues(2, 3, 4);vs.PrintValues(); // Ausgabe: 2 3 4vs++;vs.PrintValues(); // Ausgabe; 3 4 5

}}

}

Beispiel 7.11.b

class Program{

static void Main(string[] args){

ValueSet vs1 = new ValueSet(10);vs1.AddValues(2, 3, 4);vs1.PrintValues(); // Ausgabe: 2 3 4ValueSet vs2=vs1;vs2.PrintValues(); // Ausgabe: 2 3 4

Page 80: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 80 -

vs2=++vs1;vs1.PrintValues(); // Ausgabe: 3 4 5vs2.PrintValues(); // Ausgabe: 3 4 5

vs2=vs1++;vs1.PrintValues(); // Ausgabe: 4 5 6vs2.PrintValues(); // Ausgabe: 4 5 6

}}

• Die Parameter (Argumente) eines überladenen Operators dürfen nicht verändert werden

Beispiel 7.11.c

namespace Beispiel{

class ValueSet{

private int capacity;private int count;private int[] values;public ValueSet(int capacity) { . . . }public void PrintValues() { . . . }private bool AddValue(int value) { . . . }public bool AddValues(params int[] values) { . . . }public static ValueSet operator ++(ValueSet v){

ValueSet tmp = new ValueSet(v.count);for (int i = 0; i < v.count; i++)

tmp.AddValue(v.values[i] + 1);return tmp;

}}class Program{

static void Main(string[] args){

ValueSet vs1 = new ValueSet(10);vs1.AddValues(2, 3, 4);vs1.PrintValues(); // Ausgabe: 2 3 4ValueSet vs2 = vs1;vs2.PrintValues(); // Ausgabe: 2 3 4

vs2 = ++vs1;vs1.PrintValues(); // Ausgabe: 3 4 5vs2.PrintValues(); // Ausgabe: 3 4 5

vs2 = vs1++;vs1.PrintValues(); // Ausgabe: 4 5 6vs2.PrintValues(); // Ausgabe: 3 4 5

}}

}

Page 81: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 81 -

Binäre Operatoren

• Überladene relationale Operatoren müssen bool als Rückgabetyp liefern

Beispiel 7.11.d

namespace Beispiel{

class ValueSet{

private int capacity;private int count;private int[] values;public ValueSet(int capacity) { . . . }public void PrintValues() { . . . }public bool AddValues(params int[] values) { . . . }public static bool operator == (ValueSet v, int value){

for (int i = 0; i < v.count; i++)if(v.values[i]==value) return true;

return false;}

}class Program{

static void Main(string[] args){

ValueSet vs = new ValueSet(10);vs.AddValues(2, 3, 4);if(vs==4)

Console.WriteLine("4 enthalten");else

Console.WriteLine("4 nicht enthalten");}

}}

• Beim Überladen relationaler Operatoren müssen jeweils die korrespondierenden Operatoren überladen werden:

== und != , <= und >= , < und >

Beispiel 7.11.d (erweitert)

public static bool operator != (ValueSet v, int value){

for (int i = 0; i < v.count; i++)if (v.values[i] == value) return false;

return true;}

• wird '==' überladen, sollte auch Equals() und GetHashCode() überladen werden

Page 82: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 82 -

Beispiel 7.11.d (erweitert)

public override bool Equals(object obj){

if (this == (int)obj)return true;

elsereturn false;

}

Beispiel 7.11.e

namespace Beispiel{

class ValueSet{

private int capacity;private int count;private int[] values;public ValueSet(int capacity) { . . . }public void PrintValues() { . . . }

public bool AddValues(params int[] values) { . . . }private bool AddValue(int value) { . . . } private bool NextGreaterValue(ref int value) { . . . }private bool GetMin(out int min) { . . . }private void Union (ValueSet v) { . . . }public static ValueSet operator + (ValueSet v1, ValueSet v2){

ValueSet tmp = new ValueSet(20);tmp.Union(v1);tmp.Union(v2);return tmp;

}}class Program{

static void Main(string[] args){

ValueSet vs1 = new ValueSet(20);vs1.AddValues(9, 7, 5, -3);vs1.PrintValues();ValueSet vs2 = new ValueSet(20);vs2.AddValues(-5, 5, 3);vs2.PrintValues();ValueSet vs3 = new ValueSet(20);vs3=vs1+vs2;vs3.PrintValues(); // Ausgabe: 9 7 5 -3 -5 3 vs1+=vs2;vs1.PrintValues(); // Ausgabe: 9 7 5 -3 -5 3

}}

}

• wird ein binärer Operator operator überladen, so wird die zugehörige Zuweisung operator = implizit ebenfalls überladen

Page 83: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 83 -

8. Spezielle Klassen in C#

8.1 Der Datentyp object und die Klasse Object

• alle Objekttypen in C# (einfache Datentypen, Enumerations, Stukturen, Klassen) sind von der Klasse Object abgeleitet

Methoden der Klasse Object

bool ReferenceEquals(object, object)

Vergleich der Referenzen zweier Objekte, liefert true wenn Referenzen gleich sind, sonst false

bool Equals(object)

wie ReferenceEquals, aber überschreibbar

int GetHashCode()

liefert Hash-Code eines Objektes

Type GetType()

liefert den Datentyp eines Objektes

object MemberwiseClone()

kopiert ein Objekt und liefert Referenz darauf zurück

string ToString()

liefert den vollen Namen einer Klasse incl. namespace

void Finalize()

gibt Ressourcen (Speicher) einer Klasse frei

Beispiel

int i = 1;Console.WriteLine(i.GetType()); // Ausgabe: 'System.Int32'

Page 84: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 84 -

Gleichheit von Objekten/Referenzen

• Zwei Objekte obj1 und obj2 sind typgleich, wenn sie vom selben Typ sind aber unterschiedliche Instanzwerte (Feldwerte) besitzen

Beispiel

class MyClass{

public i=1;}MyClass o1 = new MyClass();MyClass o2 = new MyClass();o2.i = 2;

• Zwei Objekte obj1 und obj2 sind gleich, wenn sie vom selben Typ sind, gleiche Instanzwerte besitzen, aber ihre Referenzen auf unterschiedliche Speicheradressen verweisen

Beispiel

class MyClass{

public i=1;}MyClass o1 = new MyClass();MyClass o2 = new MyClass();

• Zwei Objekte obj1 und obj2 sind identisch, wenn sie vom selben Typ sind und ihre Referenzen auf dieselbe Speicheradresse verweisen

Beispiel

class MyClass{

public i=1;}MyClass o1 = new MyClass();

MyClass o2 = o1;

• Für den Vergleich auf Identität (Referenzvergleich) existieren 3 Möglichkeiten:

− Operator '=='

− Object.ReferenceEquals(Object, Object)

− Equals(Object)

Sie liefern true, wenn die Referenzen beider Objekte gleich sind

Page 85: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 85 -

Beispiel

MyClass o1 = new MyClass();MyClass o2 = new MyClass();if (Object.ReferenceEquals(o1, o2))

Console.WriteLine("gleich"); else

Console.WriteLine("ungleich"); //Ergebnis: ungleichif (o1 == o2)

Console.WriteLine("gleich"); else

Console.WriteLine("ungleich"); //Ergebnis: ungleich

Beispiel

MyClass o1 = new MyClass();MyClass o2 = o1;if (Object.ReferenceEquals(o1, o2))

Console.WriteLine("gleich"); //Ergebnis: gleichelse

Console.WriteLine("ungleich"); if (o1 == o2)

Console.WriteLine("gleich"); //Ergebnis: gleichelse

Console.WriteLine("ungleich");

Beispiel

int i=1;int j=i;if(Object.ReferenceEquals(i,j))

Console.WriteLine("gleich");else

Console.WriteLine("ungleich"); //Ergebnis: ungleichif(i==j)

Console.WriteLine("gleich"); //Ergebnis: gleichelse

Console.WriteLine("ungleich");

• um zwei komplexe Objekte auf Wertegleichheit zu vergleichen, kann die Methode Equals überladen werden (Unterschied zu ReferenceEquals

• Zur Überprüfung von Typgleichheit: Object.GetType()

Page 86: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 86 -

8.2 Zeichenketten

8.2.1 Der Datentyp string und die Klasse String

• C#-Syntax definiert Grunddatentyp string

• Datentyp string wird in .NET auf die Klasse String abgebildet

• Zeichenketten sind Referenztypen

• als string/String definierte Zeichenketten sind immutable, d.h. sie können durch ihre Methoden nicht überschrieben werden

Eigenschaften der Klasse String

Chars-Eigenschaft

Zugriff auf einzelne String-Zeichen durch nullbasierten Index

Length-Eigenschaft

Lesender Zugriff auf die Anzahl der char-Zeichen eines String

Beispiel

string s = "Hallo";Console.WriteLine("{0} {1}", s1.Length, s1[1]); // Ausgabe: '5 a'

• eine Änderung des Strings über die Chars-Eigenschaft ist nicht möglich

Beispiel

string s = "Hallo";s[1] = 'e'; // Fehler

⇒ das Objekt selbst würde verändert werden: Verletzung der immutable-Eigenschaft

Page 87: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 87 -

Überladene Operatoren der Klasse String

Zuweisungsoperator =

− bewirkt das Erzeugen eines String-Objektes (char-Folge + Längenwert) im Heap und Referenz darauf (String-Variable)

− werden mehrere gleiche Strings (identische char-Folgen) erzeugt, so wird nur einmal Speicherplatz im Heap allokiert. Alle String-Referenzen zeigen dann auf denselben Heap-Bereich

Beispiel

string s1 = "Hallo";string s2 = s1;Console.WriteLine("{0} {1}", s1, s2); // Ausgabe: 'Hallo Hallo'string s2 = "World";Console.WriteLine("{0} {1}", s1, s2); // Ausgabe: 'Hallo World'

Beispiel

string s1 = "World";string s2 = "World";Console.WriteLine("{0} {1}", s1.GetHashCode(), s2.GetHashCode());

• Wird der Wert einer String-Variablen geändert, so wird ein neues String-Objekt erzeugt und das alte gelöscht

Stringverkettungsoperator +

− verkettet mehrere Strings miteinander oder Strings mit arithmetischen Ausdrücken

− Verkettungsausdrücke werden von links nach rechts abgearbeitet

Syntax

<stringverkettung> ::=<string> + <string> | <string> + <arithm-ausdruck> | <arithm-ausdruck> + <string>

Beispiel

int i = 3;double d = 3.14;string s = "Hallo";string r;r = s + s +", World";Console.WriteLine("{0}", r); // Ausgabe: 'HalloHallo, World'r = i + " ist nicht " + d;Console.WriteLine("{0}", r); // Ausgabe; '3 ist nicht 3,14'r = i + d +" ist anders ";Console.WriteLine("{0}", r); // Ausgabe: '6,14 ist anders'

Page 88: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 88 -

Stringverkettungsoperator +=

verkettet einen linken String mit einem rechten oder mit rechtem arithmetischen Ausdruck

Syntax

<stringverkettung> ::=<string> += <string> | <string> += <arithm-ausdruck>

Beispiel

int i = 3;double d = 3.14;string s = "Ergebnis ";s += d;Console.WriteLine("{0}", s); // Ausgabe: 'Ergebnis 3,14's += " ungleich " + i;Console.WriteLine("{0}", s); // Ausgabe: 'Ergebnis 3,14 ungleich 3'

Methoden der Klasse String

String(char[] f)

Konstruktor. Initialisiert eine neue Instanz der String-Klasse mit dem durch ein Array von Zeichen angegebenen Wert.

String(char c, int i)

Konstruktor. Initialisiert eine neue Instanz der String-Klasse mit einer Anzahl i char-Werten

static int Compare(string s1, string s2)

Vergleicht die Strings und gibt int-Zahl zurück, die die lexikalische Beziehung der beiden Strings angibt Wert < 0 wenn s1 kleiner s2 Wert = 0 wenn s1 gleich s2 Wert > 0 wenn s1 größer s2

int IndexOf(string s)

Gibt den Index des ersten Vorkommens des angegebenen String in dieser Instanz an

string Insert(int i, string s)

Fügt einen String s an einer Indexposition i in die Instanz ein.

string Remove(int i1, int i2)

Löscht eine Anzahl i2 von Zeichen ab der Position i1 aus der Instanz.

string PadLeft (int i, char c) / string PadRight (int i, char c)

Richtet die Zeichen dieser Instanz links/rechtsbündig aus und füllt die rechte/linke Seite mit Zeichen c aus, um eine angegebene Gesamtlänge i zu erreichen.

Page 89: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 89 -

static string Concat(string, string, ...)

Verkettet eine oder mehrere Strings und liefert den Ergebnisstring

string To Lower() / string ToUpper()

Gibt eine in Klein-/Großbuchstaben konvertierte Kopie der Instanz zurück.

string Trim(char[] f)

Entfernt sämtliche Zeichen aus einer in einem Array f angegebenen Menge von Zeichen am Anfang und am Ende der Instanz.

string Substring(int i1, int i2)

Gibt eine Teilzeichenfolge dieser Instanz, beginnend mit Position i1 der Länge i2 zurück.

string[] Split(char[] f)

Gibt ein string-Array zurück, das die Teilzeichenfolgen der Instanz enthält, die durch Elemente eines angegebenen char-Arrays getrennt sind

Beispiel

char[] f = {'H','a','l','l','o'};string s1 = new String(f);Console.WriteLine("{0}", s1); // Ausgabe: 'Hallo'

string s2 = "Welt"; s2 = String.Concat(String.Concat(s1, ", ", s1), " ", s2);Console.WriteLine("{0}", s2); // Ausgabe: 'Hallo, Hallo Welt'

s2 = s2.Remove(s2.IndexOf(" "+s1), s1.Length+1);Console.WriteLine("{0}", s2); // Ausgabe: 'Hallo, Welt'

s2 = s2.Insert(s2.IndexOf(" "), " schöne, neue");Console.WriteLine("{0}", s2); // Ausgabe: 'Hallo, schöne, neue Welt'

char[] fc = {',', ' '};string[] fs = s2. Split(fc);Console.WriteLine("{0} \n{1}", fs[0], fs[2]); // Ausgabe: 'Hallo

neue '

Page 90: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 90 -

8.2.2 Die Klasse StringBuilder

• im Namensraum System.Text definiert

• StringBuilder-Objekte sind Zeichenketten, die durch die Klassenmethoden selbst geändert werden können

• Kapazität einer StringBuilder-Instanz:

− aktueller Speicherraum zur Aufnahme eines Strings

− beginnt, wenn nicht explizit anders im Konstruktor festgelegt, mit 16 Zeichen

− bei späterer Erweiterung des Strings erweitert sich die Kapazität in den Schritten

32, 64, 128, 256, ... MaxCapacity

− MaxCapacity ist implementierungsabhängig, theoretisch: 231-1 Zeichen möglich

Eigenschaften der Klasse StringBuilder

Capacity-Eigenschaft

Zugriff auf die Kapazität einer Klasseninstanz

MaxCapacity-Eigenschaft

Lesender Zugriff auf die maximale Kapazität einer Klasseninstanz

Chars-Eigenschaft

Zugriff auf einzelne Zeichen durch nullbasierten Index

Length-Eigenschaft

Zugriff auf die Anzahl der char-Zeichen einer StringBuilder-Instanz

Methoden der Klasse StringBuilder

StringBuilder(int i)

Konstruktor. Erstellt eine neue Instanz der StringBuilder-Klasse mit der Anfangskapazität i1

StringBuilder(int i1, int i2)

Konstruktor. Erstellt eine neue Instanz der StringBuilder-Klasse mit der Anfangskapazität i1 und der maximalen Kapazität i2

StringBuilder(string s)

Konstruktor. Erstellt eine neue Instanz der StringBuilder-Klasse mit einer Anfangskapazität, die sich aus s.Length ergibt und initialisiert sie mit s

StringBuilder Append(string s)

Fügt eine Kopie von s an das Ende dieser Instanz an. Liefert Referenz auf die Instanz zurück

Page 91: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 91 -

StringBuilder Insert(int i, string s)

Fügt eine Kopie von s an der Zeichenposition i in die Instanz ein. Liefert Referenz auf die Instanz zurück

StringBuilder Replace(string s1, string s2)

Ersetzt in der Instanz alle Vorkommen einer Zeichenfolge s1 durch die Zeichenfolge s2.

string ToString()

Konvertiert den Wert der Instanz in eine String.

Beispiel

string s = "Hallo Welt";StringBuilder sb = new StringBuilder();sb.Append(s);Console.WriteLine("{0} {1}", sb, sb.Capacity); // Ausgabe: 'Hallo Welt 16'

⇒ Startkapazität 16

sb.Insert(6, "schöne neue");Console.WriteLine("{0} {1}", sb, sb.Capacity); // Ausgabe: 'Hallo schöne neue Welt 32'

sb[sb.Length++] = '!';Console.WriteLine("{0}", sb); // Ausgabe: 'Hallo schöne neue Welt!'

s = sb.ToString();s = s.ToUpper();sb.Replace(sb.ToString(), s);Console.WriteLine("{0}", sb); // Ausgabe: 'Hallo schöne neue Welt 32'

Page 92: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 92 -

8.3 Arrays

• Array: Feld von Objekten gleichen Typs (homogener Container)

• Arrayelemente können einen beliebigen Typ aufweisen, z. B. auch einen Arraytyp.

• Ein Array kann eindimensional oder mehrdimensional sein

• Ein Array kann unverzweigt oder verzweigt sein

Syntax

arrays-declaration

array-declaration

jagged-array-declaration

Page 93: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 93 -

8.3.1 Unverzweigte Arrays

• entsprechen strukturell den Feldern in C/C++

Indexnotation für unverzweigte Arrays

Syntax

array-declaration

typenew= [ constant

,

]

typenew= [

,

] array-initializer

;

array-initializer

type [

,

] name

array-initializer

{

,

}expression

,

array-initializer

=

Page 94: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 94 -

• Varianten:

− Deklaration einer Referenzvariable für ein ein- bis mehrdimensionales Array definiert

− Erzeugen eines Array-Objektes im Heap und Zuweisung der Referenz an die Referenzvariable

− Erzeugen eines Array-Objektes im Heap und gleichzeitige Initialisierung mit Werten möglich

− Erzeugen eines Array-Objektes im Heap und Zuweisung der Referenz an die Referenzvariable bereits bei der Deklaration

• Zugriff auf Array-Elemente durch Index-Notation

<array-variable>[ <index> [ , <index> ]... ]

• Numerische Arrayelemente sind standardmäßig auf 0 festgelegt, Verweiselemente auf NULL, Boolsche auf false

Beispiel

int[ , ] a;a = new int[2,3]; // 2 Zeilen, 3 Spalten Matrix

a[0,2] = 6;// oderint[ , ] a = new int[ , ] {{0,0,6},{0,0,0}};// oderint[ , ] a = {{0,0,6},{0,0,0}};// Fehlerint[ , ] a; a = {{0,0,6},{0,0,0}}

• Die Größe des Arrays kann zur Laufzeit festgelegt werden

Page 95: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 95 -

Operatoren is und as

Syntax

<is-expression> ::=

<expression> is <type>

• liefert true, wenn der Ausdruck von dem angegebenen Typ ist oder in ihn konvertiert werden kann, sonst false

Syntax

<as-expression> ::=

<expression> as <type>

• liefert den typgewandelten Ausdruck, wenn der Ausdruck in angegebenen Typ konvertiert werden kann, sonst null

• entspricht: <expression> is <type> ? (<type>) <expression> : (<type>) null

Beispiel 8.3.1.a

static void Main(string[] args){

object[] a = new object[10];a[0]=12;a[1]="Hallo";a[2]=22.31;foreach (object o in a){

if(o is int)Console.WriteLine("{0} (Integer-Wert)", o);

if(o is string)Console.WriteLine("{0} (String-Wert)", o);

if(o is double)Console.WriteLine("{0} (Double-Wert)", o);

}}

Page 96: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 96 -

8.3.2 Die Klasse Array

• Arrays wird in .NET auf die Klasse Array abgebildet

• Array besitzt 7 Eigenschaften und 36 z.T. überladene Methoden

Eigenschaften der Klasse Array

Length-Eigenschaft

Liest die Anzahl der Elemente in allen Dimensionen eines Array

Rank-Eigenschaft

Liest den Rang (Anzahl der Dimensionen) eines Array

Beispiel

int[,] b = new int[2,3];Console.WriteLine("{0} {1}", b.Length, b.Rank); // Ausgabe: '6 2'

Methoden der Klasse Array

int GetLength(int i)

Gibt die die Anzahl der Elemente in der Dimension i des Array zurück.

static int IndexOf(Array a, object o)

Sucht nach dem Objekt(wert) o und gibt den Index des ersten Vorkommens innerhalb des gesamten eindimensionalen Array zurück.

static void Sort(Array a)

Sortiert die Elemente in einem eindimensionalen Array

void CopyTo(Array a, int i)

Kopiert alle Elemente der eindimensionalen Array-Instanz in das eindimensionale Array a, beginnend am angegebenen Index i von a.

Beispiel

int[,] b = new int[2,3]; Console.WriteLine("{0} {1}", b.GetLength(0), b.GetLength(1),); // Ausgabe: '2 3'

string[] a;a = new string[] {"Hallo", "das", "war", "meine", "Welt"};Console.WriteLine("{0} {1}", Array.IndexOf(a, "war"), a.Length); // Ausgabe: '2 5'

Array.Sort(a);for(int i=0; i<a.Length; i++)Console.Write("{0} ", a[i]); // Ausgabe: 'das Hallo meine war Welt'

Page 97: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 97 -

8.3.3 Verzweigte Arrays

• Verzweigtes Array (jagged array): Array, dessen Elemente Arrays sind

Indexnotation für verzweigte Arrays

Syntax

jagged-array-declaration

typenew= [ constant

,

]

;

type [

,

] name[

,

]

[

,

]

• Deklaration und Instanziierung können zusammengefaßt werden

• Die Verzweigungen können dann wie Arrays Instanziiert bzw. Initialisiert werden

• Elemente verzweigter Arrays sind Verweistypen und werden mit null initialisiert.

Beispiel

int[][] a = new int[3][];a[0] = new int[2];a[1] = new int[4];a[2] = new int[3];a[0][1] = 9;a[1][2] = 4;a[2][0] = 7;

Beispiel

int[,][] m = new int[2, 4][];m[0,0]=new int[]{1,2,3};m[0, 1] = new int[] { 1, 2, 3, 4, 5, 6 };m[1, 2] = new int[7];Console.WriteLine("{0}", m[0,1][4]); //Ausgabe: 5

Beispiel

int[][,] n = new int[4][,];n[0] = new int[,] { { 1, 2 }, { 3, 4 } };n[1] = new int[,] { { 1, 2, 3 }, { 4, 5, 6 } };

Page 98: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 98 -

n[2] = new int[3,2];Console.WriteLine("{0}", n[0][1,1]); //Ausgabe: 4

8.4 Die Klasse Type

• Reflektion

Abfrage von Typinformationen aus einer Assembly zur Laufzeit

• Die Klasse Type stellt Methoden, Felder und Eigenschaften zur Analyse von Datentypen einer Anwendung bereit

Eigenschaften der Klasse Type

Namespace-Eigenschaft

Liest den Namespace, in der der Typ deklariert ist

BaseType-Eigenschaft

Liest den Basistyp, von der der Typ abgeleitet ist

Methoden der Klasse Type

public FieldInfo[] GetFields()

Gibt die (öffentlichen, nicht-statischen) Felder eines Typs als Objekte der Klasse FieldInfo in ein Array zurück. FieldInfo enthält Eigenschaften und Methoden zur Auswertung der Merkmale eines Feldes

public MethodInfo[] GetMethods()

Gibt die (öffentlichen, nicht-statischen) Methoden eines Typs als Objekte der Klasse MethodInfo in ein Array zurück. MethodInfo enthält Eigenschaften und Methoden zur Auswertung der Merkmale einer Methode

public ParameterInfo[] GetParameters()

Gibt die Parameter einer Methode eines Typs als Objekte der Klasse ParameterInfo in ein Array zurück. ParameterInfo enthält Eigenschaften und Methoden zur Auswertung der Merkmale eines Parameters

Page 99: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 99 -

• 3 Möglichkeiten zur Erzeugung eines System.Type-Objektes für einen Datentyp:

Methode GetType

• bei Vorliegen einer Instanz eines zu untersuchenden Datentyps kann die von Object geerbte Methode GetType aufgerufen werden

Beispiel

MyClass m = new MyClass();Type type = m.GetType();

statische Methode GetType

• Liegt keine Instanz vor, kann der zu untersuchenden Datentyp durch die statische Methode GetType der Klasse Type aufgerufen werden

Beispiel

Type type = Type.GetType("Beispiel.MyClass");

Operator typeof

• Liegt keine Instanz vor, kann der zu untersuchenden Datentyp auch durch Anwendung des Operators typeof aufgerufen werden

Syntax

<typeof-expression> ::=

typeof ( <type> )

• liefert das System.Type-Objekt für den angegebenen Datentyp

Beispiel 8.4.a

namespace Beispiel{

class MyClass{

public int field1;public char[] field2;private int field3;public bool Method1(int param) { return true; }public int Method2(ref int param1, char param2) { return 1; }

}class Program{

static void Main(string[] args){

Page 100: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 100 -

Type type = typeof(MyClass); Console.WriteLine("Namespace: {0}", type.Namespace); Console.WriteLine("Basistyp : {0}", type.BaseType); Console.WriteLine("Felder:");foreach(FieldInfo field in type.GetFields())

Console.WriteLine(" {0} {1}", field.FieldType, field.Name);Console.WriteLine("Methoden:");foreach(MethodInfo method in type.GetMethods()){

Console.WriteLine(" {0}", method.Name);foreach(ParameterInfo param in method.GetParameters())

Console.WriteLine(" {0}", param.ParameterType);}

}}

}

Page 101: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 101 -

9 Klassen-Hierarchien

• Klassenhierarchien sind Beziehungen von Klassen im Sinne von Spezialisierung/Generalisierung

Beispiel

Ober- und Unterbegriffe in der Sprache

Fahrzeug

Landfahrzeug Wasserfahrzeug

PKW LKW

Generalisierung

Spezialisierung

• Eine von einer Basisklasse abgeleitete Klasse erbt alle Member (Felder und Methoden) der Basisklasse. Zusätzlich können weitere Member definiert werden.

Beispiel

Eigenschaften von Fahrzeug (Basisbegriff)

− Halter

− Preis

Eigenschaften von Wasserfahrzeug (abgeleiteter Begriff)

− Halter

− Preis

− Verdrängung

Page 102: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 102 -

UML: Hierarchien

• Hierarchien werden im Klassendiagramm durch einen nicht ausgefüllten Pfeil von der Unterklasse (abgeleitete Klasse) zur Oberklasse (Basisklasse) dargestellt

Beispiel

PKW

personenzahlkofferraumvolumen

Fahrzeug

halterpreis

Landfahrzeug

kilometerstand

Anfahren()

Wasserfahrzeug

verdrängung

Ankern()

LKW

ladefläche

Beladen()

Page 103: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 103 -

9.1 Vererbung

9.1.1 Ableitungsdeklaration

Syntax (Vervollständigung: Vererbung)

class-declaration

class-modifier class name

{

class-member

}

class-base:

class-base

class-type

• in C# ist nur Einfachvererbung möglich

• Modifizierer static in der abgeleiteten Klassen nicht zulässig

• Modifizierer sealed in der Basisklasse nicht zulässig

Beispiel

class Fahrzeug{

int halter;float preis;

}class Landfahrzeug : Fahrzeug{

int kilometerstand;Anfahren(){ };

}class PKW : Landfahrzeug{

int personenzahl;int kofferraumvolumen;

}

Page 104: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 104 -

Beispiel 9.1.1.a

namespace Beispiel{

class ValueSet{

private int count;private int[] values = new int[100];public bool AddValues(params int[] values) { . . . }

}class NamedValueSet: ValueSet{

private string name;public bool AddNamedValues(string name, params int[] values){

this.name=name;foreach (int element in values)

for (int j = 0; j < this.count; j++)if (this.values[j] == element) return false;

foreach (int element in values) // Elemente einfügenthis.values[this.count++] = element;

return true;}

}class Program1{

static void Main(string[] args){

ValueSet vs = new ValueSet();vs.AddValues(4, 9, 7, 5, -3);NamedValueSet nvs = new NamedValueSet();nvs.AddNamedValues("Menge 1", 3, 7, -8);

}}

}

• ein mit protected in einer Basisklasse deklariertes Member erlaubt den Zugriff aus allen davon abgeleiteten Klassen

Beispiel (Änderungen im vorhergehenden Beispiel)

protected int count;protected int[] values = new int[100];

Page 105: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 105 -

9.1.2 Konstruktoren und Destruktoren

• Konstruktoren einer Basisklasse werden nicht an die abgeleitete Klasse vererbt

Beispiel 9.1.2.a

namespace Beispiel{

class ValueSet{

protected int count;protected int capacity;protected int[] values;public ValueSet(int capacity) { . . . }public bool AddValues(params int[] values) { . . . }

}class NamedValueSet : ValueSet{

private string name;public NamedValueSet(int capacity, string name){

this.capacity = capacity;this.values = new int[capacity];this.name = name;

}}class Program1{

static void Main(string[] args){

ValueSet vs = new ValueSet(50);vs.AddValues(4, 9, 7, 5, -3);NamedValueSet nvs = new NamedValueSet(50, "Wertemenge1");nvs.AddValues(3, 7, -8);

}}

}

Implizite Konstruktorverkettung

• implizite Top-down-Konstruktorverkettung

Wird bei der Instanziierung eines Klassenobjektes einer abgeleiteten Klasse keine Konstruktoren der Basisklassen explizit aufgerufen, so werden zunächst die parameterlosen Standard-Konstruktoren aller in einer Hierarchie vorausgehenden Basisklassen aufgerufen

Beispiel

Beispiel

class A{

Page 106: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 106 -

private int a; public A() { Console.WriteLine("A() aufgerufen"); }}class B : A{ private int b; public B() { Console.WriteLine("B() aufgerufen"); }}class C : B{ private int c; public C(int c) { this.c = c; Console.WriteLine("C(int c) aufgerufen"); }}class Program{ static void Main(string[] args) { C c_obj = new C(3); }}

Beispiel (Ergänzung zum vorhergehenden Beispiel)

class ValueSet{

protected int count;protected int capacity;protected int[] values;public ValueSet() { }public ValueSet(int capacity) { . . . }public bool AddValues(params int[] values) { . . . }

}

explizite Konstruktorverkettung

• explizite Konstruktorverkettung

Aufruf eines Basisklassenkonstruktoren aus einer abgeleiteten Klasse heraus mit base

Page 107: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 107 -

Syntax (Wiederholung aus Kapitel 7.5)

constructor-declaration

constructor-modifier name

argument

( )

block

base:

this

parameter( )

• base bezeichnet einen Konstruktor der Basisklasse

• Argumente: Liste aktueller Parameter und bestimmt durch ihre Anzahl und den Datentyp den konkreten Konstruktor der Basisklasse

• this bezeichnet einen Konstruktor der eigenen Klasse

Beispiel 9.1.2.b

namespace Beispiel{

class ValueSet{

protected int count;protected int capacity;protected int[] values;public ValueSet(int capacity) { . . . }public bool AddValues(params int[] values) { . . . }

}class NamedValueSet : ValueSet{

private string name;public NamedValueSet(int capacity, string name): base(capacity){

this.name = name;}

}class Program1{

static void Main(string[] args){

ValueSet vs = new ValueSet(50);

Page 108: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 108 -

vs.AddValues(4, 9, 7, 5, -3);NamedValueSet nvs = new NamedValueSet(50, "Wertemenge1");nvs.AddValues(3, 7, -8);

}}

}

Destruktoren

• Destruktoren einer Basisklasse werden nicht an die abgeleitete Klasse vererbt

• implizite Bottom-up-Destruktorverkettung

Sobald der Garbage Collector auf ein nicht mehr referenziertes Objekt einer abgeleiteten Klasse stößt, wird zunächst vollständig der Destruktor dieser Klasse und danach erst der der Basisklasse ausgeführt

9.1.3 Basisklassen-Member

Überladen von Basisklassen-Methoden

• überladene Basisklassen-Methoden

Methode einer Basisklasse wird in einer abgeleiteten Klasse mit gleichem Namen und anderer Signatur definiert

Verdecken von Basisklassen-Membern

• Verdeckte Member

Member (Felder, Eigenschaften und Methoden), die mit identischem Namen und Parameterliste sowohl in einer Basisklasse als auch in einer abgeleiteten Klasse definiert sind

• Memberf einer Basisklasse werden durch Member mit dem Zugriffsmodifizierer new in der abgeleiteten Klasse verdeckt

Beispiel 9.1.3.a

namespace Beispiel{

class ValueSet{

protected int count;protected int[] values = new int[100];public bool AddValues(params int[] values) { . . . }public void PrintValues(){

for (int i = 0; i < count; i++)Console.Write("{0} ", values[i]);

Console.WriteLine();

Page 109: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 109 -

}}class NamedValueSet : ValueSet{

private string name;public bool AddNamedValues(string name, params int[] values) { . . . }public new void PrintValues(){

Console.Write("{0}: ", name);for (int i = 0; i < count; i++)

Console.Write("{0} ", values[i]);Console.WriteLine();

}}class Program1{

static void Main(string[] args){

ValueSet vs = new ValueSet();vs.AddValues(4, 9, 7, 5, -3);vs.PrintValues(); // Ausgabe: 4 9 7 5 -3NamedValueSet nvs = new NamedValueSet();nvs.AddNamedValues("Menge 1", 3, 7, -8);nvs.PrintValues(); // Ausgabe: Menge 1: 3 7 -8

}}

}

Memberzugriff mit base

• der Zugriff auf ein (verdecktes) Member (Feld, Eigenschaft, Methode)einer Basisklasse aus einer abgeleiteten Klasse heraus erfolgt durch

base . field-namebase . property-namebase . method-name( parameters )

• base ist eine implizite Referenz und damit an eine konkrete Klasseninstanz gebunden

• base ist sinnvoll bei Zugriff auf verdeckte Methoden

Beispiel 9.1.3.b

namespace Beispiel{

class ValueSet{

protected int count;protected int[] values = new int[100];public bool AddValues(params int[] values) { . . . }public void PrintValues() { . . . }

}class NamedValueSet : ValueSet

Page 110: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 110 -

{private string name;public bool AddNamedValues(string name, params int[] values) { . . . }public new void PrintValues(){

Console.Write("{0}: ", name);base.PrintValues();

}}class Program1{

static void Main(string[] args){

ValueSet vs = new ValueSet();vs.AddValues(4, 9, 7, 5, -3);vs.PrintValues(); // Ausgabe: 4 9 7 5 -3NamedValueSet nvs = new NamedValueSet();nvs.AddNamedValues("Menge 1", 3, 7, -8);nvs.PrintValues(); // Ausgabe: Menge 1: 3 7 -8

}}

}

Page 111: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 111 -

9.2 Polymorphie

Frühes Binden (statisches Binden)

• Frühes Binden ist die Zuweisung von Routinen (Methoden, Operatoren) zu ihren Objekten (Daten) bereits zum Zeitpunkt der Übersetzung

• In Klassenhierarchien erfolgt die Zuweisung von überladenen oder verdeckten Methoden zu Klassenobjekten durch den Compiler bereits zur Übersetzungszeit.

Beispiel 9.2.a

namespace Beispiel{

class ClassA{

public void Method(){

Console.WriteLine("A-Methode aufgerufen");}

}class ClassB : ClassA{

public new void Method(){

Console.WriteLine("B-Methode aufgerufen");}

}class ClassC : ClassA{

public new void Method(){

Console.WriteLine("C-Methode aufgerufen");}

}class Program{

static void Main(string[] args){

ClassA objA = new ClassA();ClassB objB = new ClassB();ClassC objC = new ClassC();objA.Method(); //Ausgabe: A-Methode aufgerufenobjB.Method(); //Ausgabe: B-Methode aufgerufenobjC.Method(); //Ausgabe: C-Methode aufgerufen

}}

}

Page 112: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 112 -

Beispiel 9.2.b

namespace Beispiel{

class ClassA{

public void Method(){

Console.WriteLine("A-Methode aufgerufen");}

}class ClassB : ClassA{

public new void Method(){

Console.WriteLine("B-Methode aufgerufen");}

}class ClassC : ClassA{

public new void Method(){

Console.WriteLine("C-Methode aufgerufen");}

}class Program{

static void Main(string[] args){

ClassA obj=null;string ereignis=Console.ReadLine();if (ereignis == "A")

obj = new ClassA();if (ereignis == "B")

obj = new ClassB();if (ereignis == "C")

obj = new ClassC();obj.Method();

}}

}

• jedes Objekt einer abgeleiteten Klasse ist zugleich auch Objekt der Basisklasse

Spätes Binden (dynamisches Binden)

• Binden einer Methode an ein Klassenobjekt erst zur Laufzeit (Polymorphie) durch:

− Deklaration der Methode in der Basisklasse als virtuell (Modifizierer virtual) und

− Überschreiben dieser Methode in der abgeleiteten Klasse (Modifizierer override)

Page 113: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 113 -

• virtual vor einer verdeckten Methode einer Basisklasse bietet der verdeckenden Methode der abgeleiteten Klasse polymorphes Verhalten an

• override vor einer Methode, die eine virtuelle Methode verdeckt, bewirkt polymorphes Verhalten

Beispiel (Modifikation des vorhergehenden Beispiels)

namespace Beispiel{

class ClassA{

public virtual void Method() { . . . }}class ClassB : ClassA{

public override void Method() { . . . }}class ClassC : ClassA{

public override void Method() { . . . }

}class Program{

static void Main(string[] args){

ClassA obj=null;string ereignis=Console.ReadLine();if (ereignis == "A")

obj = new ClassA();if (ereignis == "B")

obj = new ClassB();if (ereignis == "C")

obj = new ClassC();obj.Method();

}}

}

• die Kombination von virtual mit static oder abstract ist nicht erlaubt

• die Kombination von override mit new nicht erlaubt

• Polymorphie hat besondere Bedeutung bei sog. inhomogenen Kollektionen

Beispiel 9.2.c

namespace Beispiel{

class ValueSet{

protected int count;protected int capacity;public virtual void PrintValues() { }

Page 114: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 114 -

public virtual bool AddValues(params int[] values) {return false;}public virtual bool AddValues(params string[] values) {return false;}

}class IntValueSet : ValueSet{

private int[] values;public IntValueSet(int capacity){

base.capacity = capacity; this.values = new int[capacity];

}public override void PrintValues(){

for (int i = 0; i < base.count; i++)Console.Write("{0} ", this.values[i]);

Console.WriteLine();}public override bool AddValues(params int[] values){

foreach (int element in values)for (int j = 0; j < base.count; j++)

if (this.values[j] == element) return false;foreach (int element in values)

this.values[base.count++] = element; return true;

}}class StringValueSet : ValueSet{

private string[] values;public StringValueSet(int capacity){

base.capacity = capacity;values = new string[capacity];

}public override void PrintValues(){

for (int i = 0; i < count; i++)Console.Write("{0} ", values[i]);

Console.WriteLine();}public override bool AddValues(params string[] values){

foreach (string element in values)for (int j = 0; j < base.count; j++)

if (this.values[j] == element) return false;foreach (string element in values)

this.values[count++] = element;return true;

}}class Program1{

static void Main(string[] args){

ValueSet[] vs = new ValueSet[5];

Page 115: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 115 -

vs[0] = new IntValueSet(50);vs[0].AddValues(4, 9, 7, 5, -3);vs[0].PrintValues();vs[1] = new StringValueSet(20);vs[1].AddValues("Anna", "Hannes", "Willi", "Paul");vs[1].PrintValues();

}}

Page 116: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 116 -

9.3 Abstrakte Klassen und Methoden

Abstrakte Klasse

• Klasse, von der keine Instanzen erzeugt werden können

• Abstrakte Klassen werden durch den Modifizierer abstract gekennzeichnet

• eine abstrakte Klasse kann abstrakte Methoden (auch Eigenschaften, Indexer und Ereignisse) enthalten

Abstrakte Methode

• Methodendeklaration, die keinen Anweisungsblock besitzt und durch den Modifizierer abstract gekennzeichnet ist

• eine von einer abstrakten Basisklasse abgeleitete Klasse muß

− alle abstrakten Methoden der Basisklasse mit override überschreiben oder

− selbst als abstrakte Klasse mit abstract gekennzeichnet werden

• eine Methode, die mittels override eine abstrakte Methode einer Basisklasse überschreibt, zeigt polymorphes Verhalten

Beispiel

namespace Beispiel{

abstract class ValueSet{

protected int count;protected int capacity;public abstract void PrintValues();public abstract bool AddValues(params int[] values); public abstract bool AddValues(params string[] values);

}class IntValueSet : ValueSet{

private int[] values;public IntValueSet(int capacity) { . . . }public override void PrintValues() { . . . }public override bool AddValues(params int[] values) { . . . }

}class StringValueSet : ValueSet{

private string[] values;public StringValueSet(int capacity)

Page 117: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 117 -

public override void PrintValues() { . . . }public override bool AddValues(params string[] values) { . . . }

}class Program1{

static void Main(string[] args){

ValueSet[] vs = new ValueSet[5];vs[0] = new IntValueSet(50);vs[0].AddValues(4, 9, 7, 5, -3);vs[0].PrintValues();vs[1] = new StringValueSet(20);vs[1].AddValues("Anna", "Hannes", "Willi", "Paul");vs[1].PrintValues();

}}

}

Beispiel 9.3.a

namespace Beispiel{

abstract class ValueSet{

protected int count;protected int capacity;public abstract void PrintValues();public abstract bool AddValues(params object[] values);

}class IntValueSet : ValueSet{

private int[] values;public IntValueSet(int capacity) { . . . }

public override void PrintValues() { . . . }public override bool AddValues(params object[] values){

foreach (object element in values) if(!(element is int)) // Exception{

Console.WriteLine("Zuweisung eines Nicht-Int-Elements");return false;

}foreach (object element in values)

for (int j = 0; j < base.count; j++)if (this.values[j] == (int) element) return false;

foreach (int element in values)this.values[count++] = (int) element;

return true;}

}class StringValueSet : ValueSet{

private string[] values;public StringValueSet(int capacity) { . . . }public override void PrintValues() { . . . }

Page 118: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 118 -

public override bool AddValues(params object[] values) {

foreach (object element in values)if (!(element is string)) // Exception{

Console.WriteLine("Zuweisung eines Nicht-String-Elements");return false;

}foreach (object element in values)

for (int j = 0; j < count; j++)if (this.values[j] == (string) element) return false;

foreach (string element in values)this.values[count++] = (string) element;

return true;}

}class Program1{

static void Main(string[] args){

ValueSet[] vs = new ValueSet[5];vs[0] = new IntValueSet(50);vs[0].AddValues(4, 9, 7, 5, -3);vs[0].PrintValues();vs[1] = new StringValueSet(20);vs[1].AddValues("Anna", "Hannes", "Willi", "Paul");vs[1].PrintValues();

}}

}

• besitzt eine Klasse eine abstrakte Methode, dann muß sie selbst als abstract definiert werden

Page 119: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 119 -

UML: Abstrakte Klassen

• Abstrakte Klasse/Methoden werden im Klassendiagramm kursiv dargestellt

Beispiel

# count : int# capacity : int

+ PrintValues( ) : void+ AddValues( values : object[] ) : bool

ValueSet

- values : int[]

+ IntValueSet( capacity : int ) + PrintValues( ) : void+ AddValues( values : object[] ) : bool

IntValueSet

- values : string[]

+ StringValueSet( capacity : int ) + PrintValues( ) : void+ AddValues( values : object[] ) : bool

StringValueSet

Page 120: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 120 -

9.4 Schnittstellen

• Schnittstellen dienen der Deklaration von Methodenschemata, die Klassen, die diese Schnittstellen implementieren, einhalten müssen

9.4.1 Schnittstellendeklaration

Syntax

interface-declaration

interface-modifier interface name

{

interface-member

}

interface-modifier

interface-base:

partial

interface-base

interface-type

,

access-modifier

• interfac-basee: eine Schnittstelle kann mehrere Basisschnittstellen besitzen: die Schnittstelle erbt dann alle Memberdeklarationen der Basisschnittstellen

• Schnittstellennamen beginnen konventionsgemäß mit einem großen 'I'

Page 121: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 121 -

Syntax

interface-member

interface-method-declaration

interface-property-declaration

interface-event-declaration

interface-indexer-declaration

• Member einer Schnittstelle sind die von den Basisschnittstellen vererbten Member und die in der Schnittstelle selbst deklarierten Member.

• Schnittstellenmember enthalten keine Anweisungsblöcke

Syntax

interface-method-declaration

void

name parameter(type )

new

;

Syntax

interface-property-declaration

name {type }

new

get ;

get ;

set ;

set ;

• Alle Schnittstellenmember sind implizit public

Page 122: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 122 -

9.4.2 Schnittstellenimplementierung

• Schnittstellen können von Klassen (und auch Strukturen) implementiert werden.

Syntax (Vervollständigung: Interface-Implementation)

class-declaration

class-modifier class name

{

class-member

}

class-base:

class-base

class-type

interface-type , interface-type

• die von einer Schnittstelle übernommenen Klassenmember

− müssen in Name, Parametern und Rückgabetyp mit dem Schnittstellenmember übereinstimmen

− dürfen nur public implementiert werden

− können abstract oder virtual sein

Beispiel

namespace Beispiel{

public interface IFliegen{

void Start();}public interface IKraftstoff{

void Tanken(int menge);}class Motorflieger : IFliegen, IKraftstoff{

public void Start(){

Console.WriteLine("Motorflieger startet");}public void Tanken(int menge)

Page 123: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 123 -

{Console.WriteLine("Motorflieger tankt {0} Liter", menge);

}}class Segelflieger{

public void Start(){

Console.WriteLine("Segelflieger startet");}

}class Program{

static void Main(string[] args){

Motorflieger m = new Motorflieger();Segelflieger s = new Segelflieger();m.Tanken(200); // Ausgabe: Motorflieger tankt 200 Literm.Start(); // Ausgabe: Motorflieger startets.Start(); // Ausgabe: Segelflieger startet

}}

}

• innerhalb einer Vererbungshierarchie werden Schnittstellen vererbt

Beispiel

namespace Beispiel{

interface IGegenstand{

string Besitzer { get; set;}}interface IFliegen{

void Start();}class Luftfahrzeug : IGegenstand, IFliegen{

protected string besitzer; //protected o.k., da mit Eigenschaft Besitzer zugegriffenpublic string Besitzer{

get { return besitzer; }set { this.besitzer = value; }

}public void Start(){

Console.WriteLine("Flieger von {0} startet", this.besitzer);}

}class Motorflieger : Luftfahrzeug{}

Page 124: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 124 -

class Segelflieger : Luftfahrzeug{}class Program{

static void Main(string[] args){

Luftfahrzeug[] obj = new Luftfahrzeug[10];obj[0] = new Motorflieger();obj[0].Besitzer = "Meier";obj[1] = new Segelflieger();obj[1].Besitzer = "Müller";obj[0].Start(); // Ausgabe: Flieger von Meier startetobj[1].Start(); // Ausgabe: Flieger von Meier startet

}}

}

• Werden Schnittsellen-Member einer Basisklasse virtuell definiert und in den abgeleiteten Klassen mit override überschrieben, zeigen sie dort polymorphes Verhalten

Beispiel

namespace Beispiel{

interface IGegenstand{

string Besitzer { get; set;}}interface IFliegen{

void Start();}class Luftfahrzeug : IGegenstand, IFliegen{

protected string besitzer;public string Besitzer{

get { return besitzer; }set { this.besitzer = value; }

}public virtual void Start(){ }

}class Motorflieger : Luftfahrzeug{

public override void Start(){

Console.WriteLine("Motorflieger von {0} startet", this.besitzer);}

}class Segelflieger : Luftfahrzeug{

public override void Start()

Page 125: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 125 -

{Console.WriteLine("Segelflieger von {0} startet", this.besitzer);

}}class Program{

static void Main(string[] args){

Luftfahrzeug[] obj = new Luftfahrzeug[10];obj[0] = new Motorflieger();obj[0].Besitzer = "Meier";obj[1] = new Segelflieger();obj[1].Besitzer = "Müller";obj[0].Start(); // Ausgabe: Motorflieger von Meier startetobj[1].Start(); // Ausgabe: Motorflieger von Müller startet

}}

}

• Abstrakte Kassen, die Schnittstellen implementieren, können deren Methoden abstrakt definieren

Beispiel 9.4.2.a

namespace Beispiel{

public interface IPrintable{

void PrintValues();}public interface ISetBasics{

bool AddValues(params object[] values);}abstract class ValueSet : IPrintable, ISetBasics{

protected int count;protected int capacity;public abstract void PrintValues();public abstract bool AddValues(params object[] values);

}class IntValueSet : ValueSet{

private int[] values;public IntValueSet(int capacity) { . . . }public override void PrintValues() { . . . }public override bool AddValues(params object[] values) { . . . }

}class StringValueSet : ValueSet{

private string[] values;public StringValueSet(int capacity) { . . . }public override void PrintValues() { . . . }public override bool AddValues(params object[] values) { . . . }

}

Page 126: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 126 -

class Program1{

static void Main(string[] args){

ValueSet[] vs = new ValueSet[5];vs[0] = new IntValueSet(50);vs[0].AddValues(4, 9, 7, 5, -3);vs[0].PrintValues();vs[1] = new StringValueSet(20);vs[1].AddValues("Anna", "Hannes", "Willi", "Paul");vs[1].PrintValues();

}}

}

Page 127: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 127 -

UML: Schnittstellen

• Schnittstellen werden durch den Stereotyp <<interface>> über dem Schnittstellennamen gekennzeichnet

• die Implementation einer Schnittstelle wird durch einen nicht ausgefüllten Pfeil mit gestrichelter Linie dargestellt

Beispiel

# count : int# capacity : int

+ PrintValues( ) : void+ AddValues( values : object[] ) : bool

ValueSet

- values : int[]

+ IntValueSet( capacity : int ) + PrintValues( ) : void+ AddValues( values : object[] ) : bool

IntValueSet

- values : string[]

AddValues( values : object[] ) : bool

StringValueSet

PrintValues( ) : void

<<interface>> ISetBasics

<<interface>> IPrintable

+ StringValueSet( capacity : int ) + PrintValues( ) : void+ AddValues( values : object[] ) : bool

Page 128: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 128 -

9.4.3 Explizite Implementierung

Beispiel

namespace Beispiel{

interface IMotor{

void KraftstoffzufuhrErhöhen();void TurboladerZuschalten();

}class Fahrzeug : IMotor{

public void KraftstoffzufuhrErhöhen(){

Console.WriteLine("Kraftstoffzufuht erhöht");}public void TurboladerZuschalten(){

Console.WriteLine("Turbolader zugeschaltet");}

}class Program{

static void Main(string[] args){

Fahrzeug meinPkwj = new Fahrzeug();meinPkw.KraftstoffzufuhrErhöhen();meinPkw.TurboladerZuschalten();

}}

}

• Explizite Implementierung

Definition eines Members unter der Bezeichnung

iinterface-name . member-name

• bei expliziter Implementierung dürfen in der Memberdefinition keine Modifizierer angegeben werden

Beispiel

namespace Beispiel{

interface IMotor{

void KraftstoffzufuhrErhöhen();void TurboladerZuschalten();

}class Fahrzeug : IMotor

Page 129: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 129 -

{public void KraftstoffzufuhrErhöhen(){

Console.WriteLine("Kraftstoffzufuht erhöht");}void IMotor.TurboladerZuschalten(){

Console.WriteLine("Turbolader zugeschaltet");}

}class Program{

static void Main(string[] args){

Fahrzeug meinPkw = new Fahrzeug();meinPkw.KraftstoffzufuhrErhöhen();meinPkw.TurboladerZuschalten(); // Fehler

}}

}

• Zugriff auf ein explizit implementiertes Member erfolgt immer über eine Schnittstelleninstanz, der eine Referenz auf ein Objekt der Klasse, die die Schnittstelle implementiert, zugewiesen wurde:

interface-name interface-variable //Schnittstelleninstanz definiereninterface-variable = object-referenz //Schnittstelleninstanz referenziereninterface-variable . member //Schnittstellemember-Aufruf

Beispiel

namespace Beispiel{

interface IMotor{

void KraftstoffzufuhrErhöhen();void TurboladerZuschalten();

}class Fahrzeug : IMotor{

public void KraftstoffzufuhrErhöhen(){

Console.WriteLine("Kraftstoffzufuht erhöht");}void IMotor.TurboladerZuschalten(){

Console.WriteLine("Turbolader zugeschaltet");}

}class Program{

static void Main(string[] args){

Fahrzeug meinPkw = new Fahrzeug();IMotor meinMotor = meinPkw;

meinPkw.KraftstoffzufuhrErhöhen();

Page 130: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 130 -

meinMotor.TurboladerZuschalten(); // o.k.}

}}

Beispiel

namespace Beispiel{

interface ILandfahrzeug{

void Geschwindigkeit();}interface IWasserfahrzeug{

void Geschwindigkeit();}class Fahrzeug : ILandfahrzeug, IWasserfahrzeug{

void ILandfahrzeug.Geschwindigkeit(){

Console.WriteLine("Geschwindigkeit in km/h");}void IWasserfahrzeug.Geschwindigkeit(){

Console.WriteLine("Geschwindigkeit in Knoten");}

}class Program{

static void Main(string[] args){

Fahrzeug meinBoot = new Fahrzeug();IWasserfahrzeug wfGeschw = meinBoot;wfGeschw.Geschwindigkeit();

}}

}

Page 131: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 131 -

10. Weitere spezielle Klassen in C#

10.1 Streams und Dateien

10.1.1 Die Klasse Stream

• Stream

Datenfluß von einer Quelle zu einem Ziel, der eine Folge von Bytes repräsentiert

− Streams auf Byte-Ebene abstrahieren von den spezifischen Interpretationen einer Bytefolge (z.B. als String, als verschlüsselte Information etc.) in einer Anwendung

− Gleicher Programmcode zum Lesen/Schreiben von Bytefolgen unabhängig davon, von wem und wohin ein Datenstrom gesendet wird

− Anwendung kann somit unabhängig von den spezifischen Details eines Streams entwickelt werden

• Quelle/Ziel eines Streams kann sein:

− Dateien

− Netzwerkverbindungen

− periphere Geräte (Drucker etc.)

− Speicherblöcke

• Klasse Stream

− Abstrakte Basisklasse aller Streamklassen.

− stellt grundlegende Eigenschaften und Methoden für diese Streamklassen bereit

− Namespace: System.IO

• abgeleitete Klassen:

Stream

FileStream

NetworkStream

MemoryStream

CryptoStream

GZipStream

Page 132: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 132 -

• 2 Typen von Stream

− Base-Streams: lesen/schreiben direkt aus/in den Datenstrom

− Pass-Through-Streams: ergänzen Base-Streams um spezielle Funktionalitäten

• 3 grundlegende Merkmale von Streams:

− Lesen: Daten werden von einem Stream in eine Datenstruktur übertragen.

− Schreiben: Daten werden aus einer Datenstruktur in einen Stream übertragen.

− Positionieren: aktuelle Position in einem Stream wird abgefragt und bearbeitet. (wahlfreier Zugriff)

10.1.2 Die Klasse FileStream

• Klasse FileStream

− stellt Eigenschaften und Methoden zum byteweisen Schreib- und Lesezugriff auf Dateien in einem Dateisystem bereit

− Methoden zum Öffnen und Schließen dieser Dateien

− Positionieren, Lesen Schreiben

− puffert Daten (Standard 8 KByte), somit:

− Erhöhung der E/A-Geschwindigkeit

− Namespace: System.IO

Eigenschaften der Klasse FileStream

Length-Eigenschaft

ruft Länge des Streams in Bytes ab

Position-Eigenschaft

ruft Position des Streams ab oder legt diese fest

Methoden der Klasse FileStream

FileStream(Path, FileMode)

FileStream(Path, FileMode, FileAccess)FileStream(Path, FileMode, FileAccess, FileShare)FileStream(Path, FileMode, FileAccess, FileShare, int)Konstruktoren, erstellen eine neue Instanz der FileStream-Klasse

Page 133: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 133 -

• Path-Parameter

String mit Dateiname und ggf. Pfadangabe

• FileMode-Parameter (Enumeration)

bestimmt, wie das Betriebssystem das File (String) öffnen soll

Appendöffnet oder erzeugt eine Datei, Dateizeiger auf Dateiende (Anfügen)

Createerzeugt oder überschreibt eine Datei

CreateNewerzeugt eine Datei, existiert die Datei bereits: IOException

Openöffnet eine Datei, existiert die Datei nicht: FileNotFoundException

OpenOrCreateöffnet oder erzeugt eine Datei

Truncateöffnet eine Datei und löscht deren Inhalt

• FileAccess-Parameter (Enumeration)

bestimmt, wie das File zugegriffen werden darf

Readöffnet Datei ausschließlich für LesezugriffWriteöffnet Datei ausschließlich für SchreibzugriffReadWriteöffnet Datei für Lese- und Schreibzugriff

• FileShare-Parameter (Enumeration)

bestimmt, ob und wie mehrere Anwendungen/Threads auf das File zugreifen können

Nonekein Zugriff durch weitere Anwendungen/Threads auf die DateiReaddarf durch weitere ausschließlich zum Lesen geöffnet werdenWritedarf durch weitere ausschließlich zum Schreiben geöffnet werdenReadWritedarf durch weitere zum Lesen und Schreiben geöffnet werden

• int-Parameter

positiver Int32-Wert, bestimmt die Größe des Puffers

Page 134: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 134 -

Beispiel

FileStream fs;fs = new FileStream("D:\\temp\\test.txt", FileMode.Append, FileAccess.Write, FileShare.Read);

int Read (byte[] array, int offset, int count)

Liest einen Byteblock aus dem Stream und schreibt die Daten in das Arrayoffset: Byteoffset im Array, ab dem aus dem Stream eingelesen werden soll. count: maximale Anzahl der zu lesenden Bytes.

Rückgabewert: Anzahl gelesenen Bytes.

void Write (byte[] array, int offset, int count)

Schreibt einen Block von Bytes aus dem Array in den Streamoffset: Byteoffset im Array, ab dem in den Stream kopiert werden. count: maximale Anzahl der zu schreibenden Bytes

int ReadByte ()

Liest ein Byte aus dem Stream

void WriteByte (byte value )

Schreibt ein Byte value in den Stream

long Seek (long offset, SeekOrigin origin)

Legt die aktuelle Position des Streams auf den angegebenen Wert festoffset: Position relativ zu originorigin: Bezugspunkt für offset

Rückgabewert: neue Position im Stream.

void Flush ()

Leert den Puffer für den Stream gibt die Daten auf das zugrunde liegende Gerät aus

void Close ()

Schließt den Stream

• SeekOrigin-Parameter (Enumeration)

BeginAnfang des StreamsCurrentAktuelle Position im StreamEndEnde des Streams

Page 135: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 135 -

Beispiel

static void Main(string[] args){

byte[] arr = { 10, 20, 30, 40, 50, 60, 70, 80};FileStream fs = new FileStream("D:\\test.txt",FileMode.Create);fs.Write(arr, 0, arr.Length);fs.Close();

}

Beispiel

static void Main(string[] args){

byte[] arr = { 10, 20, 30, 40, 50, 60, 70, 80 };FileStream fs = new FileStream("D:\\test.txt",FileMode.Create);fs.Write(arr, 0, arr.Length);Console.ReadLine(); //Programmunterbrechung

fs.Flush();Console.ReadLine(); //Programmunterbrechung

fs.Close();}

Beispiel

static void Main(string[] args){

byte[] arr = new byte[10];FileStream fs = new FileStream("D:\\test.txt",FileMode.Open);fs.Seek(4, SeekOrigin.Begin);fs.Read(arr, 4, 3);fs.Seek(1, SeekOrigin.Begin);fs.Read(arr, 0, 2);fs.Close();for (int i = 0; i < 10; i++)Console.Write("{0} ", arr[i]);

}

Page 136: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 136 -

• Inhalt der Datei test.txt mit dem Editor betrachtet

• Bytefolgen eines Streams müssen sinnvoll interpretiert werden, damit sie Informationen liefern

Beispiel

20 117 220 4 88 157 58 14

Text (z.B. "AC&86<%u")

Binär (z.B. als double-Wert 22.345)

Bytefolge

interpretiert als

• Klassen zur Interpretation von Streams als

− Text --> StreamReader, StreamWriter

− Binär -->BinaryReader, BinaryWriter

• alles Pass-Through-Klassen: ergänzen ein Stream-Objekt um weitere Funktionalitäten

Page 137: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 137 -

10.1.3 Die Klassen StreamReader und StreamWriter

• von Stream abgeleitete Klassen können nur für die Ein-/Ausgabe von Bytefolgen verwendet werden.

• StreamReader/StreamWriter stellen Methoden zur Ein-/Ausgabe von Zeichen in einer bestimmten Codierung zur Verfügung

Textformate

• ASCII-Zeichensatz

− Verschlüsselung der Zeichen durch 7 Bit (0 .. 127)

− keine Umlaute möglich

− US-Standard

• ANSI-Zeichensatz (ISO 8859-1)

− Verschlüsselung der Zeichen durch 8 Bit (0 .. 255)

− Umlaute und andere sprachspezifischer Schriftzeichen möglich

− Europa-Standard

• Unicode

− Zeichen werden abstrakt definiert und jedem Zeichen eine Nummer zugeordnet

− derzeit fast 96.382 unterschiedliche Zeichen

− abstrakte Zeichen müssen in Bitmuster transformiert werden: Unicode Transformation Format (UTF)

− verschiedene Transformationen: UTF-7, UTF-8, UTF-16, UTF-32

• UTF-8

− Standard in .NET

− Unicode-Zeichen 0..127 entsprechen dem ASCII-Zeichensatzes und werden in einem Byte verschlüsselt

− Unicode-Zeichen ab 128 werden in 2 bis 4 Byte verschlüsselt

− in .NET ist die Länge eines Strings (Anzahl der Zeichen) <= Anzahl der Bytes

Page 138: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 138 -

Eigenschaften der Klasse StreamWriter

EndOfStream-Eigenschaft

ruft das Ende des Streams ab. Wenn aktuelle Stream-Position am Ende: true, sonst false

Methoden der Klasse StreamWriter

StreamWriter (Stream)

Konstruktor. Erzeugt Instanz der StreamWriter-Klasse zum Schreiben in den angegebenen Stream mit Standard-Codierung

StreamWriter (Stream, Encoding)

wie oben, Encoding: Codierung (UTF-8, ASCII ...)

StreamWriter (Path)

wie oben, Erzeugt direkt Instanz der StreamWriter-Klasse ohne vorherigen FileStream Path: String aus Dateiname und ggf. Pfad

Beispiel

FileStream fs = new FileStream("D:\\temp\\test.txt", FileMode.Create);StreamWriter sw = new StreamWriter(fs, Encoding.ASCII);

Beispiel

StreamWriter sw = new StreamWriter("D:\\temp\\test.txt");

void Write ( <parameter> )

Schreibt <parameter> in den TextStream

Syntax der <parameter> wie bei Console.Write

void WriteLine ( <parameter> )

wie Write, nur mit Zeilenabschluß '\n'

void Flush ()

Leert den Puffer für den Writer gibt die Daten auf den zugrunde liegenden Stream aus

void Close ()

Schließt das StreamWriter-Objekt und den zugrunde liegenden Stream.

Page 139: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 139 -

Methoden der Klasse StreamReader

StreamReader (Stream)

Konstruktor. Erzeugt Instanz der StreamReader-Klasse zum Lesen aus dem angegebenen Stream mit Standard-Codierung

StreamReader (Stream, Encoding)

Konstruktor. Encoding: Codierung (UTF-8, ASCII ...)

StreamReader (Path)

Konstruktor. Erzeugt direkt Instanz der StreamReader-Klasse ohne vorherigen FileStreamPath: String aus Dateiname und ggf. Pfad

int Read ()

Liest das nächste Zeichen aus dem Stream, gibt es als Int32 zurück und verschiebt die Position um ein Zeichen nach vorn. Ist kein weiteres Zeichen im Stream wird -1 zurückgegeben. Wie Console.Read.

string ReadLine ()

Liest eine Zeile von Zeichen aus dem Stream und gibt die Daten als Zeichenfolge zurück. Bei Stream-Ende wird null zurückgegeben. Wie Console.ReadLine.

string ReadToEnd ()

Liest den Stream von der aktuellen Position bis zum Ende des Streams und gibt ihn als String zurück

void Close ()

Schließt das StreamWriter-Objekt und den zugrunde liegenden Stream.

Beispiel

static void Main(string[] args){

string s;FileStream fs = new FileStream("D:\\test.txt", FileMode.Create);StreamWriter sw = new StreamWriter(fs);while ((s = Console.ReadLine()) != null)sw.WriteLine(s);

sw.Flush();StreamReader sr = new StreamReader(fs);fs.Seek(0, SeekOrigin.Begin);while(!sr.EndOfStream)Console.WriteLine(sr.ReadLine());sw.Close();sr.Close();

}

Page 140: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 140 -

10.1.4 Die Klassen BinaryReader und BinaryWriter

• BinaryReader/BinaryWriter stellen Methoden zur Ein-/Ausgabe von primitive Datentypen als Binärwerte zur Verfügung

• BinaryReader stellt für jeden Grunddatentyp eine Read-Methode zur Verfügung

byte ReadByte() - liest ein Bytelong ReadInt64() - liest ein 8-Byte-Integerdouble ReadDouble()- liest einen 8-Byte Gleitkommawert. . .

• BinaryWriter stellt für jeden Grunddatentyp eine Überladung der Write-Methode zur Verfügung

void Write ( Byte ) - schreibt ein Bytevoid Write ( Long ) - schreibt ein 8-Byte-Integervoid Write ( Double ) - schreibt einen 8-Byte Gleitkommawert. . .

• um Daten, die im Binärformat vorliegen, richtig interpretieren zu können, muß man deren Datentyp kennen

Beispiel

static void Main(string[] args){

int d = 123456; // entspricvht INT32FileStream fs;fs = new FileStream("D:\\test.txt", FileMode.Create);BinaryWriter bw = new BinaryWriter(fs);bw.Write(d); // Wriote für INT32bw.Flush();BinaryReader br = new BinaryReader(fs);fs.Seek(0, SeekOrigin.Begin);Console.WriteLine(br.ReadInt32());//for(int i=0; i<fs.Length; i++)// Console.WriteLine(br.ReadByte());

}

Beispiel

static void Main(string[] args){

fs = new FileStream("D:\\test.txt", FileMode.Open);BinaryReader br = new BinaryReader(fs);for(int i=0; i<fs.Length; i++)Console.WriteLine(br.ReadByte());

}

Page 141: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 141 -

10.1.5 Spezielle Klassen zur Dateiarbeit

Die Klasse File, Methoden

• Stellt statische Methoden zum Kopieren, Verschieben, Umbenennen, Erstellen, Öffnen, Löschen und Anfügen von Dateien zur Verfügung

FileStream Create ( Path )

Erstellt eine Datei im angegebenen Pfad-String FileStream fs = File.Create("D:\\temp\\test.txt");

FileStream Open ( Path, FileMode, FileAccess, FileShare )

Öffnet einen FileStream auf dem angegebenen Pfad-StringFileStream fs = File.Open("D:\\test.txt", FileMode.Open);

String ReadAllText ( Path )

Öffnet eine Textdatei, liest alle Zeilen der Datei in eine Zeichenfolge und schließt die Datei

void WriteAllText ( Path, String )

Erstellt/Überschreibt eine Datei mit dem String und schließt die Datei dannstring s;s = File.ReadAllText("D:\\test1.txt");File.WriteAllText("D:\\test2.txt",s);

void Delete ( Path )

Löscht die angegebene DateiFile.Delete("D:\\test2.txt",s);

void Move ( SourcePath, DestPath )

Verschiebt eine Datei von einem Verzeichnis SourcePath in ein Verzeichnis DestPathFile.Move("D:\\test.txt", "D:\\temp\\test_neu.txt");

void SetAttributes ( Path, FileAttributes )

Setzt File-Attribute für eine Datei

FileAttributes GetAttributes ( Path )

Liest File-Attribute einer Dateienum FileAttributes: Hidden, ReadOnly ...File.SetAttributes("D:\\test.txt", FileAttributes.Hidden);

Page 142: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 142 -

Die Klasse Directory, Methoden

• Stellt statische Methoden zum Erstellen, Verschieben und Auflisten in Verzeichnissen und Unterverzeichnissen zur Verfügung

DirectoryInfo CreateDirectory ( Path )

Erstellt ein Verzeichnis/Unterverzeichnis PathDirectory.CreateDirectory("D:\\TEST");

void DeleteDirectory ( Path )

Löscht ein leeres Verzeichnis/Unterverzeichnis PathDirectory.DeleteDirectory("D:\\TEST");

string[] GetFiles ( Path )

Gibt alle Dateien eines Verzeichnisses in ein String-Array ausstring[] s_array = Directory.GetFiles("D:\\temp");

foreach (string s in s_array) Console.WriteLine(s);

Die Klasse DriveInfo, Methoden und Eigenschaften

• Stellt Methoden und Eigenschaften zum Abfragen von Laufwerkinformationen bereit.

DriveInfo[] GetDrives ()

Stellt für jedes logische Laufwerk ein DriveInfo-Objekt in einem Array bereit.

IsReady-Eigenschaft

Ruft einen Bool-Wert ab, der angibt, ob ein Laufwerk bereit ist

Name-Eigenschaft

Ruft den Namen eines Laufwerks als String ab.

DriveType-Eigenschaft

Ruft den Typ (Festplatte, CD-LW, ...) eines Laufwerks als String ab

TotalSize-Eigenschaft

Ruft die Gesamtgröße des Speicherplatzes auf einem Laufwerk in Bytes ab

Beispiel

static void Main(string[] args){

DriveInfo[] d_array = DriveInfo.GetDrives();foreach (DriveInfo d in d_array){Console.WriteLine("Name: {0}", d.Name);Console.WriteLine("Typ : {0}", d.DriveType);if (d.IsReady == true)Console.WriteLine("Size: {0}", d.TotalSize);Console.WriteLine();

Page 143: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 143 -

}}

Page 144: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 144 -

10.2. Ausnahmen (exceptions)

• klassische Fehlerbehandlung: return-Code

Beispiel

int Modulo(int x, int y){

if (x>=0)&&(y != 0)return x % y;

elsereturn -1;

}main(){

...if (erg=Modulo(a,b) != -1)

printf("%f",erg)else

printf("Fehler: Division durch 0 oder x ist negativ");...

}

Beispiel

int Modulo(int x, int y){

if (y != 0)return x % y;

elsereturn ???;

}

• Nachteile der klassischen Fehlerbehandlung:

− uneinheitliche Behandlung von Fehlern

− Programmierer ist nicht gezwungen, auf Fehler zu reagieren

Exception-Mechanismus

• Exception (dt. Ausnahme): Laufzeitfehler, der ein definiertes Fehlerobjekt (der Klasse Exception) erzeugt, das die speziellen Fehlerinformationen kapselt

• Ablauf nach Auslösen ("Werfen der Exception") einer Exception (z.B. Division durch 0):

− der aktuelle Block, der die Exception ausgelöst hat wird verlassen und in den übergeordneten Block zurückgekehrt bzw.

− die Methode, die Exception ausgelöst hat, wird ohne Rückgabewert beendet und zum Aufrufer der Methode zurückgekehrt

Page 145: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 145 -

− im übergeordneten Block bzw. Aufrufer wird nach einer Fehlerbehandlungsroutine für die spezielle Exception gesucht.

− wird eine Fehlerbehandlungsroutine gefunden ("Fangen der Exception"), so wird diese abgearbeitet.

− wird keine gefunden, so wiederholt sich das für den nächst-übergeordneten Block bzw. den vorhergehenden Aufrufer

− wird auch auf der obersten Hierarchieebene keine passende Fehlerbehandlungsroutine gefunden, so wird die Exception vom System gefangen und das Programm mit Fehlernachricht beendet

• Programmierer kann auf Expedites durch Fehlerbehandlungsroutine reagieren (behandelte Ausnahmen) oder nicht (unbehandelte Ausnahmen)

10.2.1 Unbehandelte Ausnahmen

Beispiel

static int Modulo(int x, int y){

return x % y;}static void Main(string[] args){

int a = 22;int b = 0;Console.WriteLine(Modulo(a, b));

}

• System wirft bei der Ausführung 22%0 eine spezielle Exception und beendet das Programm mit Ausgabe einer Nachricht:

Page 146: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 146 -

• Exception-Typ-Hierarchie (Ausschnitt)

Exception

SystemException

NullReferenceException

ArgumentException

ArgumentNullException

ArgumentOutOfRangeException

IOException

DirectoryNotFoundException

FileNotFoundException

ApplicationException

ArithmeticException

DivideByZeroException

• im .NET-Handbuch sind für jede Methode die Excepions aufgeführt, die sie auslösen kann

2 von der Basisklasse Exception geerbte Eigenschaften:

Message-Eigenschaft

String mit Fehlermeldung, die die Ursache der Ausnahme erklärt

StackTrace-Eigenschaft

String, der den Inhalt der Aufrufliste beschreibt. Letzter Methodenaufruf erscheint als zuerst.

Page 147: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 147 -

10.2.2 Behandelte Ausnahmen

• 2 Schritte bei Ausnahmebehandlung

1. Markierung des Codeabschnitts der eine Exception werfen kann (try-Block)2. Fangen und Behandlung der Exception (catch-Block)

Syntax (vereinfacht)

try-statement

try block

( )nameexception-typecatch block

finally block

• Abarbeitung der try-catch-Anweisung:

1. Werfenwirft eine Anweisung im try-Block eine Exception eines bestimmten Typs, so wird die Abarbeitung des try-Blockes sofort beendet, nach einem catch-Block für diesen Exception-Typ gesucht 2. Fangen

existiert ein solcher Block, so wird dieser abgearbeitet 3. Aufräumen

falls finally-Block existiert, wird dieser danach abgearbeitet wurde die Ausnahme gefangen wird nach der try-catch-Anweisung weitergemachtwurde sie nicht gefangen so wird wie bei unbehandelten Ausnahmen verfahren

Beispiel 10.2.2.a

static void FileWrite(string path, string text){

FileStream fs = File.Open(path,FileMode.CreateNew);StreamWriter sw = new StreamWriter(fs);sw.WriteLine(text);sw.Close();

}static void Main(string[] args){// Simulation für z.B. path = Console.ReadLine(); text = Console.ReadLine();

string path = "D:\\temp\\test.txt"; string text = "HALLO";

Page 148: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 148 -

FileWrite(path,text);Console.WriteLine("Hier geht es weiter...");

}

• 2 mögliche Exceptions:

• string path = "D:\\temp\\test.txt"; // test.txt existiert bereits (CreateNew)

string text = "HALLO";

• string path = "D:\\temp1\\test.txt"; // temp1 existiert nicht

string text = "HALLO";

• weitere Ausnahmen möglich

Beispiel 10.2.2.b

static void FileWrite(string path, string text){

FileStream fs = File.Open(path,FileMode.CreateNew);StreamWriter sw = new StreamWriter(fs);sw.WriteLine(text);sw.Close();

}static void Main(string[] args){

string path = "D:\\temp\\test.txt"; string text = "HALLO";

try{FileWrite(path, text);}catch (DirectoryNotFoundException) // Fehlerhafter Pfad{Console.WriteLine("ACHTUNG FEHLER: Verzeichnis oder Pfad existieren nicht!");}catch (IOException e) // Datei existiert bereits{Console.WriteLine("ACHTUNG FEHLER: {0}", e.Message);}catch (Exception){Console.Write("UNBEKANNTER FEHLER");}

Console.WriteLine("\n...es geht weiter...");

}

Page 149: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 149 -

• Ausgabe bei

• string path = "D:\\temp1\\test.txt"; // temp1 existiert nicht

string text = "HALLO";

• string path = "D:\\temp\\test.txt"; // test.txt existiert bereits (CreateNew)

string text = "HALLO";

• string path = "D:\\temp\test.txt"; // fehlendes '\'

string text = "HALLO";

• Reihenfolge des Auffangens der Exceptions wichtig: erst abgeleitete Ausnahme, dann erst allgemeineren Fall abfangen. (sonst Compilerfehler)

• Werden Ausnahmen gefangen, so sollten dort die aufgetretenen Fehler beseitigt werden

Page 150: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 150 -

10.2.3 Explizites Werfen von Ausnahmen

• soll ein Zustand, der vom System nicht als Ausnahme interpretiert wird, als Ausnahme behandelt werden, so muß die Exception explizit mit throw-Anweisung geworfen werden

Syntax

throw-statement

throw expression

• expression: mit new erzeugtes Objekt einer existierenden Exception-Klasse

• es existieren mehrere überladene Konstruktoren der Exception-Klassen, u.a. für die Basisklasse und entsprechend für die abgeleiteten Klassen:

Exception()

Initialisiert eine neue Instanz der Exception-Klasse.

Exception(string message)

Initialisiert eine neue Instanz der Exception-Klasse mit einer angegebenen Message-Fehlermeldung

Beispiel 10.2.3.a

static void FileWrite(string path, string text){

if(text==null)throw new ArgumentNullException(); // StandardkonstruktorFileStream fs = File.Open(path,FileMode.CreateNew);StreamWriter sw = new StreamWriter(fs);sw.WriteLine(text);sw.Close();

}static void Main(string[] args){

string path = "D:\\temp\\test.txt"; string text = null;try{FileWrite(path, text);}

catch (ArgumentNullException e) {Console.WriteLine("ACHTUNG FEHLER: {0}", e.Message);}// ... weitere catch-Blöcke

Page 151: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 151 -

Console.WriteLine("\n...es geht weiter..."); }

• Exception-Nachricht

Eigene Ausnahmen

• Für anwendungsspezifische Ausnahmesituationen sollten eigene Exception-Klassen von der Klasse ApplicationException abgeleitet werden

Beispiel 10.2.3.b

public class MyNullTextException : ApplicationException{

public MyNullTextException(string message): base(message){ }

}static void FileWrite(string path, string text){

if(text==null)throw new MyNullTextException ("Kein Text! Datei wurde nicht erzeugt.");FileStream fs = File.Open(path,FileMode.CreateNew);StreamWriter sw = new StreamWriter(fs);sw.WriteLine(text);sw.Close();

}static void Main(string[] args){

string path = "D:\\temp\\test.txt"; string text = null;

try{FileWrite(path, text);}

catch (MyNullTextException e) {Console.WriteLine("ACHTUNG FEHLER: {0}", e.Message);}// ... weitere catch-Blöcke

Console.WriteLine("\n...es geht weiter..."); }

Page 152: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 152 -

• Exception-Nachricht

• Hauptprobleme beim Einsatz von Exceptions

− Herausfinden der Stellen im Programm, an denen Exceptions auftreten können

− Feststellen des speziellen Exception-Typs

• Exceptions sinnvoll verwenden da Performanceverlust

Page 153: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 153 -

11. Klassenbeziehungen

11.1 Assoziationen

Beispiel 11.1.a

public class Person{

private string name;private string wohnort;private string strasse;private short nr;public Person(string name, string wohnort, string strasse, short nr){this.name = name;this.wohnort = wohnort;this.strasse = strasse;this.nr = nr;}

}class Program{

static void Main(string[] args){Person p1 = new Person("Cindy Meier", "HRO", "Bergstr.", 3);Person p2 = new Person("Bert Meier", "HRO", "Bergstr.", 3);}

}

Beispiel 11.1.b

public class Adresse{

private string ort;private string strasse;private short nr;public Adresse(string ort, string strasse, short nr){

this.ort = ort;this.strasse = strasse;this.nr = nr;}

}public class Person{

private string name;private Adresse wohnsitz;public Person(string name, Adresse wohnsitz){this.name = name;

Page 154: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 154 -

this.wohnsitz = wohnsitz;}

}class Program{

static void Main(string[] args){Adresse a1 = new Adresse("HRO", "Bergstr.", 3);Adresse a2 = new Adresse("M", "Parkstr.", 1);

Person p1 = new Person("Cindy Meier", a1);Person p2 = new Person("Bert Meier", a1);Person p3 = new Person("Josef Motzen", a2);}

}

UML: Assoziation

• Assoziation

− Beziehung zwischen Klassen

− wird im UML-Klassendiagramm durch Linie zwischen den assoziierten Klassen angegeben

• Assoziationsrichtung

− Richtung, aus der ein Zugriff von Objekten der einen Klasse (source) auf Objekte der anderen Klasse (target) erfolgen kann

− eine Assoziation kann unidirektional oder bidirektional sein

− Assoziationsrichtungen werden durch Pfeile am Ende der verbindenden Linie in Richtung von der source-Klasse zur target-Klasse angegeben

− keine Pfeile oder Pfeile in beide Richtungen: bidirektionale Assoziation

• Kardinalität (Multiplizität)

gibt als Zahl n/* oder Bereich n .. m an, wieviel Objekte der einen Klasse mit wieviel Objekten der andren assoziiert sein können/müssenz.B.

0 .. 1 - kann mit keinem oder einem Objekten assoziiert sein 1 - muß mit genau einem Objekt assoziiert sein3 .. 4 - muß mit mindestens 3 und kann mit bis zu 4 Objekten assoziiert sein* - kann mit keinem oder beliebig vielen Objekten assoziiert sein (synonym: 0 .. *)1 .. * - muß mit einem und kann mit bis zu beliebig vielen Objekten assoziiert sein

• Rolle

Bezeichnung, unter der ein Objekt der einen Kasse mit einem Objekt der anderen Klasse assoziiert wird

• Diagramm

Page 155: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 155 -

class 1 class 2role 1

card 1

role 2

card 2

− ein Objekt der Klasse 2 tritt in der Rolle 2 in der Klasse 1 auf und umgekehrt

− ein Objekt der Klasse 1 steht mit card2 Objekten der Klasse 2 in Beziehung und umgekehrt

Beispiel

Person

- name : string

+ Person( name : string, wohnsitz : Adresse)

Adresse

- ort : string- strasse : string- nr : short

+ Adresse( ort : string, strasse : string, nr : short)

- wohnsitz 1

*

UML: Aggregation und Komposition

• Aggregation und Komposition bilden Spezialfälle der Assoziation

• Aggregation

− Assoziation, bei der Objekte der target-Klasse Teile eines Objektes der source-Klassen bilden

− wird im Klassendiagramm durch nicht ausgefüllte Raute an der source-Klasse dargestellt

SourceClass TargetClassrole 2

card 2

• Komposition

− Assoziation, bei der Objekte der target-Klasse existenzabhängig eines Objektes der source-Klassen sind

− wird im Klassendiagramm durch ausgefüllte Raute an der source-Klasse dargestellt

Page 156: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 156 -

SourceClass TargetClassrole 2

card 2

11.2. Indizierer

Beispiel 11.2.a

public class Spieler{

public string name;public int punkte = 0; public Spieler(string name){this.name = name;}public void Gewinn(int punkte){this.punkte+=punkte;}

}class Program{

static void Main(string[] args){Spieler[] Runde1 = new Spieler[3];Runde1[0] = new Spieler("Meier");Runde1[1] = new Spieler("Motzen");Runde1[2] = new Spieler("Schmidt");

Runde1[1].Gewinn(24);for(int i=0; i<3; i++)Console.WriteLine("{0} {1}",Runde1[i].name,Runde1[i].punkte);}

}

Beispiel 11.2.b

public class Spieler // Code wie oben{

public string name;public int punkte = 0; public Spieler(string name){this.name = name;}public void Gewinn(int punkte){this.punkte+=punkte;}

Page 157: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 157 -

}public class Skatrunde{

private Spieler[] Runde = new Spieler[3];public Spieler Get(int index){return Runde[index];}public void Set(int index, string name){Runde[index] = new Spieler(name);}public void Gewinn(int index, int punkte) // Überladene Methode{Runde[index].Gewinn(punkte);}

}class Program{

static void Main(string[] args){Skatrunde Runde1 = new Skatrunde();Runde1.Set(0, "Meier");Runde1.Set(1, "Motzen");Runde1.Set(2, "Schmidt");

Runde1.Gewinn(1, 24);for (int i = 0; i < 3; i++)

Console.WriteLine("{0} {1}", Runde1.Get(i).name, Runde1.Get(i).punkte);}

}

• UML-Klassendiagramm

Skatrunde

+ Get( index: int ): Spieler+ Set( index: int, name: string ): void+ Gewinn( index: int, punkte: int): void

Spieler

+ name: string+ punkte: int = 0

+ Spieler( name: string )+ Gewinn( punkte: int ): void

- Runde

0..3

.

• ein Indizierer (Indexer) ermöglicht den Zugriff auf Klassenobjekte mittels []-Zugriffsoperator

Page 158: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 158 -

Syntax

indexer-declaration

indexer-modifier

indexer-modifier

type[type ]

method-modifier ohne static

indexthis

get-accessor{ }set-accessor

get-accessor set-accessor

,

• Indexer müssen nicht mit ganzzahligen Werten indiziert werden.

• getter-rumpf enthält Anweisungen zum lesenden Zugriff, der setter-rumpf Anweisungen zum schreibenden Zugriff auf die Elemente eines (privates) Arrays

• get-acessor muß eine return-anweisung enthalten

• Mithilfe des Schlüsselworts value wird im set-Accessor der Wert zugewiesen wird (wie bei Properties)

Beispiel 11.2.c

public class Spieler // Code wie oben{

public string name;public int punkte = 0; public Spieler(string name){this.name = name;}public void Gewinn(int punkte){this.punkte+=punkte;}

}

Page 159: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 159 -

public class Skatrunde{

private Spieler[] Runde = new Spieler[3];public Spieler this[int index]{get { return Runde[index]; }

set { Runde[index] = value; }}}class Program{

static void Main(string[] args){Skatrunde Runde1 = new Skatrunde();Runde1[0] = new Spieler("Meier");Runde1[1] = new Spieler("Motzen");Runde1[2] = new Spieler("Schmidt");

Runde1[1].Gewinn(28);for (int i = 0; i < 3; i++)Console.WriteLine("{0} {1}", Runde1[i].name, Runde1[i].punkte);}

}

Page 160: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 160 -

11.3 Enumeratoren

• Um die foreach-Anweisung für Array-Objekte einer Klasse zu verwenden, muß ein Enumerator definiert werden (die Klasse muß eine Methode GetEnumerator besitzen)

• der Compiler überführt die Anweisung

foreach( <datentyp> element in array )Console.WriteLine( element );

in eine AnweisungsfolgeIEnumerator enumerator = array.GetEnumerator();enumerator.Reset();while( enumerator.MoveNext() ){

<datentyp> element = ( <datentyp> ) enumerator.Current;Console.WriteLine( element );

}

• Ein Enumerator ist ein mit

GetEnumerator() aus dem Interface IEnumerable

erzeugtes Objekt, das mit Hilfe von

Reset(), MoveNext und Current aus dem Interface IEnumerator

auf die Elemene einer Aufzählung zugegriffen werden kann.

• Um die foreach-Anweisung für Array-Objekte einer Klasse zu verwenden, muß die Klasse die Schnittstelle IEnumerable implementieren

IEnumerable

• Schnittstelle, die einen Enumerator zur Verfügung stellt

• Namespace: System.Collections

IEnumerator GetEnumerator()

Methode, die einen Enumerator für eine Klasse erzeugt

IEnumerator

• Schnittstelle, die die Methoden/Eigenschaften für einen Enumerator zur Verfügung stellt, die von der diesen Enumerator verwendenden Klasse klassenspezifisch implementiert werden müssen

• Namespace: System.Collections

Object Current

Eigenschaft, die das aktuelle Element in der Auflistung abruft

Page 161: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 161 -

bool MoveNext()

− Setzt den Enumerator auf das nächste Element der Auflistung

− Nach Erstellen eines Enumerators wird dieser vor das erste Element positioniert

− der erste Aufruf von MoveNext positioniert den Enumerator auf das erste Element

− wird der Enumerator hinter das letzten Element positioniert, gibt MoveNext gibt false zurück

void Reset()

Setzt den Enumerator vor das erste Element der Auflistung.

Beispiel 11.3.a

public class Spieler // Code wie oben{

public string name;public int punkte = 0; public Spieler(string name){this.name = name;}public void Gewinn(int punkte){this.punkte+=punkte;}

}public class Skatrunde: IEnumerable{

private Spieler[] Runde = new Spieler[3];public Spieler this[int index]{get { return Runde[index]; }

set { Runde[index] = value; }}

// bisher Code wie obendas kann auch außerhalb geschehen, besser so, da so direkter Zugriff auf private Member

class Runde_Enumerator: IEnumerator{private Skatrunde E_Runde;private int e_index = -1;public Runde_Enumerator(Skatrunde E_Runde){this.E_Runde = E_Runde;}public object Current{get { return E_Runde[e_index]; }}public bool MoveNext(){if(e_index>=2)return false;

Page 162: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 162 -

e_index++;return true;}public void Reset(){e_index = -1;}}public IEnumerator GetEnumerator(){return new Runde_Enumerator(this);}

} class Program{

static void Main(string[] args){Skatrunde Runde1 = new Skatrunde();Runde1[0] = new Spieler("Meier");Runde1[1] = new Spieler("Motzen");Runde1[2] = new Spieler("Schmdt");

Runde1[1].Gewinn(28);foreach (Spieler sp in Runde1)Console.WriteLine("{0} {1}", sp.name, sp.punkte);}

}

Page 163: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 163 -

11.4 Collections

• Collection

Klasse, die eine Vielzahl von Objekten enthalten und verwalten kann

• 4 Collection-Klassen

− ArrayList

− Stack

− Queue

− Hashtable

• alle Collection-Klassen im namespace System.Collections definiert

• eine Collection kann Objekte unterschiedlichen Typs enthalten

11.4.1 ArrayList

• ArrayList

− Liste von Elementen, die intern auf ein Array abgebildet wird

− dynamisch in der Größe änderbar

Eigenschaften der Klasse ArrayList

Capacity-Eigenschaft

Liest die Anzahl der Elemente, die eine ArrayList enthalten kann oder legt diese fest.

Count-Eigenschaft

Liest die aktuelle Anzahl der Elemente einer ArrayList

Item-Eigenschaft

Liest/Schreibt ein Element einer ArrayList mittels Index der Form <arraylist-variable> [ <index> ]

Methoden der Klasse ArrayList

int Add (object Object)

Fügt ein Objekt an des Listenende an und gibt den Index zurück

void Insert (int Index, object Object)

Page 164: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 164 -

Fügt am angegebenen Index ein Element ein

void RemoveAt (int Index)

Entfernt ein Element am angegebenen Index

void Clear( )

Löscht alle Listenelemente

Beispiel 11.4.1.a

class Program{

static void Main(string[] args){ArrayList a = new ArrayList();a.Add(11);a.Add(22);a.Add(33);foreach (object o in a)Console.Write("{0} ", o);Console.WriteLine();a[1] = 44;foreach (object o in a)Console.Write("{0} ", o);Console.WriteLine();a.RemoveAt(1); // Entfernen beim Index 1foreach (object o in a)Console.Write("{0} ", o);Console.WriteLine();a.Insert(1, 22);foreach (object o in a)Console.Write("{0} ", o);}

}

Beispiel 11.4.1.b

class Program{

static void Main(string[] args){ArrayList a = new ArrayList();a.Add(12);a.Add("Hallo");a.Add(22.31);foreach (object o in a){if(o is int)Console.WriteLine("{0} (Integer-Wert)", o);if(o is string)Console.WriteLine("{0} (String-Wert)", o);if(o is double)Console.WriteLine("{0} (Double-Wert)", o);}

Page 165: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 165 -

}

}

Beispiel 11.4.1.c

class Apfel{ }class Birne{ }class Obstkorb{

ArrayList Korb = new ArrayList();public void Hinzu(object frucht){Korb.Add(frucht);}public void Inhalt(){int äpfel = 0;int birnen = 0;foreach (object o in Korb){if (o is Apfel)äpfel++;elsebirnen++;}Console.WriteLine("{0} Äpfel und {1} Birnen gesammelt", äpfel, birnen);}

}class Program{

static void Main(string[] args){Apfel apfel = new Apfel();Birne birne = new Birne();Obstkorb meinKorb = new Obstkorb(); meinKorb.Hinzu(apfel);meinKorb.Hinzu(birne);meinKorb.Hinzu(apfel);meinKorb.Hinzu(birne);meinKorb.Hinzu(birne);meinKorb.Inhalt(); // 2 Äpfel und 3 Birnen gesammelt}

}

Obstkorb

+ Hinzu( frucht: object ): void+ Inhalt( ): void

Apfel

.

Birne

- Korb

0..*

Page 166: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 166 -

11.4.2 Hashtable

• Hashtable

− Liste, deren Elemente aus Tupeln (object Schlüssel, object Wert) bestehen

− Zugriff auf ein Werte (Objekte) der Liste erfolgt über den Schlüssel

• Vorteil von Hashtable gegenüber ArrayList: schnelles Suchen nach Objekten

Nachteil: langsames Einfügen

• Elemente einer Hashtable sind vom Strukturtyp DictionaryEntry

Eigenschaften von DictionaryEntry

Key-Eigenschaft

Liest den Schlüssel eines Hashtable-Elements oder legt ihn fest

Value-Eigenschaft

Liest den Wert eines Hashtable-Elements oder legt ihn fest

Eigenschaften von Hashtable

Keys-Eigenschaft

Liest die Liste (ICollection) der aktuellen Schlüssel der Elemente einer Hashtable.

Values-Eigenschaft

Liest die Liste (ICollection) der aktuellen Werte (Objekte) der Elemente einer Hashtable.

Item-Eigenschaft

Liest/Schreibt ein Element einer Hashtable mittels Schlüsselindex der Form <hashtable-variable> [ <schlüssel> ]

Methoden von Hashtable

int Add (object Key, object Object)

Fügt ein mit dem angegebenen Schlüssel und Wert der Liste hinzu

void Remove(object Key)

Entfernt ein Element mit dem angegebenen Schlüssel

void Clear( )

Page 167: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 167 -

Löscht alle Listenelemente

Beispiel 11.4.2.a

class Program{

static void Main(string[] args){Hashtable h = new Hashtable();h.Add(101, "Meier");h.Add(202, "Motzen");h.Add(303, "Meier");foreach (object o in h.Values)Console.Write("{0} ", o);

Console.WriteLine();

foreach (object o in h.Keys)Console.Write("{0} ", o);Console.WriteLine();

foreach (DictionaryEntry d in h)Console.Write("({0}, {1}) ", d.Key, d.Value);Console.WriteLine();

Console.Write("{0}", h[202]);Console.WriteLine();

h.Remove(101);foreach (DictionaryEntry d in h)Console.Write("({0}, {1}) ", d.Key, d.Value);Console.WriteLine();}

}

11.4.3 Queue

• Queue

Collection nach dem FIFO-Prinzip (First In First Out)

Eigenschaften der Klasse Queue

Count-Eigenschaft

Liest die Anzahl der Elemente, die in der Queue enthalten sind

Methoden der Klasse Queue

void Enqueue (object Object)

Page 168: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 168 -

Fügt an das Ende der Queue ein Objekt hinzu

object Dequeue ( )

Entfernt das Objekt am Anfang von der Queue und gibt es zurück.

void Clear( )

Löscht alle Objekte der Queue

Beispiel 11.4.3.a

class Program{

static void Main(string[] args){Queue q = new Queue();q.Enqueue(11);q.Enqueue(22);q.Enqueue(33);foreach (object o in q)Console.Write("{0} ", o);Console.WriteLine();

Console.WriteLine("{0} entfernt", q.Dequeue());

foreach (object o in q) Console.Write("{0} ", o); Console.WriteLine();

q.Enqueue(11); foreach (object o in q) Console.Write("{0} ", o); Console.WriteLine(); } }}

11.4.4 Stack

• Stack

Collection nach dem LIFO-Prinzip (Last In First Out)

Eigenschaften der Klasse Stack

Count-Eigenschaft

Liest die Anzahl der Elemente, die im Stack enthalten sind

Page 169: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 169 -

Methoden der Klasse Stack

void Push (object Object)

Fügt an den Anfang des Stack ein Objekt hinzu

object Pop ( )

Entfernt das oberste Objekt des Stack und gibt es zurück.

object Peek ( )

Gibt das oberste Objekt des Stack zurück ohne es zu entfernen.

void Clear( )

Löscht alle Objekte des Stack

Beispiel 11.4.4.a

class Program{

static void Main(string[] args){Stack s = new Stack();s.Push(11);s.Push(22);s.Push(33);foreach (object o in s)Console.Write("{0} ", o);Console.WriteLine();

Console.WriteLine("{0} entfernt", s.Pop());

foreach (object o in s) Console.Write("{0} ", o); Console.WriteLine();

s.Push(44); foreach (object o in s) Console.Write("{0} ", o); Console.WriteLine();

}}

Page 170: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 170 -

12 Delegate und Ereignisse

12.1 Delegate

• ein Delegat ist ein Objekt, das einen Verweis auf eine Methode beschreibt

Definition eines Delegaten

Syntax

delegate-declaration

delegate-modifier

void

name

delegate-modifier

parameter(type ) ;delegate

public

protected

internal

private

new

Schnittstellen Delegate

werden bereits beim Übersetzen erstellt werden erst zur Laufzeit erstellt

können die Signaturen unterschiedlicher Methoden festlegen

legt nur eine Signatur fest

Methoden werden innerhalb der Schnittstellenklasse definiert

Delegate können innerhalb oder außerhalb von Klassen definiert werden

Page 171: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 171 -

Erzeugen und Aufruf eines Delegat-Objektes

Definition einer Delegat-Variablen

<delegat-name> <delegat-variable> ;

Erzeugen eines Delegat-Objektes

<delegat-variable> = new <delegat-name> ( <method-name> ) ;

• Voraussetzungen

− <delegat-name> ist ein bereits definierter Delegat

− <method-name> ist eine bereits definierte Methode

− die Signaturen (Rückgabewert und Parameter) des Delegaten und der Methode sind identisch

Aufruf eines Delegaten

<delegat-variable> ( [ <actual-parameter-list> ] ) ;

Beispie 12.1.a

class Program{

public delegate void fooDelegat();

static void Main(string[] args){

fooDelegat d; d = new fooDelegat(foo1); d(); d = new fooDelegat(foo2);

d();}

public static void foo1() { }

public static void foo2() { }}

Page 172: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 172 -

Beispiel12.1.b

abstract class Math{

public delegate int Delegat(int x, int y);public static int plus(int x, int y){

return x + y;}public static int mal(int x, int y){

return x * y;}

}class Program{

static void Main(string[] args){

Math.Delegat fd;fd = new Math.Delegat(Math.plus);Console.WriteLine("3+4 = {0}", fd(3, 4)); // Ausgabe: 3+4 = 7fd = new Math.Delegat(Math.mal);Console.WriteLine("3*4 = {0}", fd(3, 4)); // Ausgabe: 3*4 = 12

}}

• in C# 2.0 vereinfachte Erzeugen eines Delegat-Objektes:

für

<delegat-variable> = new <delegat-name> ( <method-name> ) ;auch

<delegat-variable> = <methoden-name> ;

Page 173: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 173 -

12.2 Ereignisse

• Ein Event (Ereignis) ist eine Nachricht, die durch eine Methode ausgelöst wird und an den ursprünglichen Aufrufer der Methode zurückgesendet wird

• Event-Source: Klasse, die ein Ereignis auslöst

Event-Sink: Klasse, die ein Ereignis verarbeitet (Client)

• Methoden die nach Auslösung eines Events durch eine Event-Sink (Client) ausgeführt werden, heißen Event-Handler

Erzeugen und Auslösen eines Ereignisses

Event-Sink Event-Source

Aufruf Methode

Auslösen Event (1)

Auslösen Event (2)

(1)

(1)

(2)

(2)

Methode

Event-Handler

• Event-Variablen werden im Event-Source definiert

Page 174: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 174 -

Syntax

event-declaration

event-modifier namedelegate-nameevent

event-modifier

method-modifier

;

Erzeugen einer Delegat-Instanz für einen Event-Handler und Binden an eine Event-Variable

<event-variable> += new <delegate-name> ( <handler-name> ) ;

• durch aufeinanderfolgende Anwendung des '+='-Operators können mehrere Handler an ein Ereignis gebunden werden

event += new delegate (handler1 ) ;event += new delegate (handler2 ) ;. . .

Entfernen eines Handlers aus einer Ereignisliste

<event-variable> -= new <delegate-name> ( <handler-name> ) ;

Auslösen eines Ereignisses im Event-Source

<event-variable> ( [ <actual-parameter-list> ] ) ;

Beispiel 12.2.a

class EventSource{

public delegate void OnEventHandler();public event OnEventHandler OnEvent; public void SourceMethode(){

OnEvent();}

} class EventSink{

static void Main(string[] args)

Page 175: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 175 -

{EventSource es = new EventSource();es.OnEvent += new EventSource.OnEventHandler(foo1);es.OnEvent += new EventSource.OnEventHandler(foo2);es.SourceMethode();es.OnEvent -= new EventSource.OnEventHandler(foo1);es.SourceMethode();

}

public static void foo1(){ } public static void foo2(){ }

}

Publisher-Subscriber-Modell

Events deklarieren

Delegat deklarieren

delegate void TimeEventHandler(int timeEvent)

event TimeEventHandler OnMinuteevent TimeEventHandler OnHour

Events auslösen

OnHour(hour)OnMinute(minute)

Publisher (Timer, Zeitgeber)

Eventhandler definieren

Events registrieren

OnMinute += new TimeEventHandler(MinuteChange)OnHour += new TimeEventHandler(HourChange)

void MinuteChange(int m) { }void HourChange(int h) { }

Subscriber (Clock, normale Uhr)

Eventhandler definieren

Events registrieren

OnMinute += new TimeEventHandler(MinuteChange)

void MinuteChange(int m) { }

Subscriber (EggClock, Eieruhr)

Events gesendet

Page 176: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 176 -

Beispiel 12.2.b

class Timer //Zeitgeber{

public delegate void TimeEventHandler(int timeEvent);public event TimeEventHandler OnMinute;public event TimeEventHandler OnHour;private int minute;private int hour;public Timer(int h, int m){

hour = h;minute = m;

}public void Run(){

OnHour(hour);OnMinute(minute);while (true){

Thread.Sleep(1000); //1 sek entspricht 1 minminute++;if (minute == 60){

minute = 0;hour++;OnHour(hour);

}OnMinute(minute);

}}

}class Clock //normale Uhr{

private int minute;private int hour;public void MinuteChange(int m){

minute = m;Console.WriteLine("Clock: {0} : {1}", hour, minute);

}public void HourChange(int h){

hour = h;}

}class EggClock //Eieruhr{

private int delay;public EggClock(int d){

delay = d;}public void MinuteChange(int m){

delay--;

Page 177: Programmierung II Einführung in C# - dblabor.fh …dblabor.fh-stralsund.de/skripte/Skript Programmierung II.pdf · Fachhochschule Stralsund. Programmierung II - 2 - 1 Einleitung

Programmierung II - 177 -

if (delay == 0)Console.WriteLine("EggClock: Alarm!!!");

}}class Program{

static void Main(string[] args){

Timer timer = new Timer(15, 57); //Aktuelle Start-Zeit: 15:57 UhrClock clock = new Clock();EggClock eggClock = new EggClock(6); //Alarm nach 6 Minuten für ein gutes Ei!timer.OnMinute += new Timer.TimeEventHandler(clock.MinuteChange);timer.OnHour += new Timer.TimeEventHandler(clock.HourChange);timer.OnMinute += new Timer.TimeEventHandler(eggClock.MinuteChange);timer.Run();

}}