Einführung in die Programmiersprache C# Kapitel 1: C# Übersicht

Transcrição

Einführung in die Programmiersprache C# Kapitel 1: C# Übersicht
C# und .NET: die Entwicklung
Einführung in die
Programmiersprache C#
Datum
Ereignis
Juni 2000
Bill Gates stellt erstmals die .NET-„Vision“ vor.
Oktober 2000
C# wird zur Standardisierung eingereicht
Januar 2002
.NET 1.0 und Visual Studio .NET 2002 werden veröffentlicht
April 2003
.NET 1.1und Visual Studio 2003 werden veröffentlicht
November 2005
.NET 2.0 und Visual Studio 2005 werden veröffentlicht
November 2006
.NET 3.0 wird veröffentlich
November 2007
.NET 3.5 und Visual Studio 2008 werden veröffentlicht
Rainer Schmidberger
[email protected]
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
se-rt
C# 1.01
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Folie 3
C# 1.01
.NET: Framework, Sprachen und Werkzeuge
VB
C++
C#
JScript
…
Common Language Specification
Web
Services
‰ Entwicklung bis heute
‰ Konzepte
‰ Architektur
User
Interface
Data and XML
Base Class Library
Visual Studio.NET
Kapitel 1: C# Übersicht
Common Language Runtime
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
se-rt
C# 1.01
1
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Quelle: Microsoft
Folie 4
2
.NET Framework
Common Intermediate Language
‰ Das .NET Framework umfasst:
Ö Laufzeitumgebung: Common Language Runtime (CLR) mit
einer für alle .NET gemeinsamen Common Intermediate
Language (CIL). Z.B. ist der Garbage Collector in der CLR
implementiert
Ö Typsystem: Common Language Specification (CLS)und
Common Type System (CTS). Alle .NET-Sprachen basieren
auf gemeinsamen Basis-Typen
Ö .NET Bibliothek: Umfangreiche (Klassen-) Bibliothek z.B. für
grafische Oberfläche, Web-Anwendungen, Datenbank,
Sockets, XML, Multi-Threading, Kryptographie usw.
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
‰ Die CIL ist der „Befehlssatz“ der Virtual Machine von .NET
Ö D.h. .NET-Anwendungen sind plattform-unabhängig in CIL
geschrieben
Ö Der CIL-Code sichert die kompatibilität zwischen den
verschiedenen .NET Programmiersprachen
Ö CIL ist eine „objektorientierte Assemblersprache“
se-rt
Folie 5
.NET Framework: ein Sprachenmix
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
C# 1.01
Folie 7
Common Language Runtime
‰ Eine .NET-Anwendung kann in unterschiedlichen Sprachen
geschrieben werden (z. B. C#, J#, C++/CLI, Visual Basic .NET)
‰ Eine Klasse, die in C# geschrieben ist, kann von einer Klasse in
Visual Basic 2005 beerbt werden. Beide Klassen können Daten
miteinander austauschen und Ausnahmen weiterreichen.
‰ Es gibt unter .NET keine „bevorzugte“ Programmiersprache.
Vorteil: Jeder kann in der Sprache seiner Wahl programmieren.
‰ Die Klassenbibliothek, das Typsystem und die Laufzeitumgebung
ist für alle .NET Sprachern gleich.
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
‰ C++/CLI nimmt
Sonderstellung ein:
wird (meistens) direkt
in Maschinencode
compiliert (d.h. CIL
wird nicht
verwendet)
se-rt
Folie 6
3
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 8
4
Common Language Runtime
Thread Support
COM Marshaler
Type Checker
Exception Manager
Security Engine
Debug Engine
IL to Native
Compilers
Code
Manager
Garbage
Collector
Class Loader
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Quelle: Microsoft
se-rt
Folie 9
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Quelle: Microsoft
Folie 11
Architektur des .NET Framework
.NET Programmiersprachen
Ein gemeinsames
Typsystem für alle
.NET Sprachen
Kapitel 2: C# Grundlagen
Umfangreiche
Klassen-Bibliothek
‰
‰
‰
‰
‰
Laufzeitumgebung
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Quelle: Microsoft
se-rt
Folie 10
5
Kommentare, Bezeichner, reservierte Wörter
Typenübersicht
Operationen
Arrays
Kontrollstrukturen
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
6
Einfaches Beispiel
UML-Darstellung
Kommentare
C#-Code
‰ Kommentierter Bereich
Person.cs
/* Dies ist ein Kommentar,
der über mehrere
Zeilen verläuft */
class Person
{
private double gehalt;
‰ Zeilenkommentar
public double getGehalt() {
return gehalt;
}
Person
int x = 1;
// Anfangswert
// ab jetzt folgen Initialisierungen
gehalt: double
public void setGehalt(int g) {
gehalt = g;
}
gehaltErhoehen()
setGehalt
getGehalt
public void gehaltErhoehen() {
gehalt = gehalt + 100;
}
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
se-rt
Folie 13
C# 1.01
Testrahmen für die Klasse Person
PersonTest.cs
donald.setGehalt(1000);
Console.WriteLine("Donald verdient " +
donald.getGehalt() + " EUR.");
donald.gehaltErhoehen();
Console.WriteLine("Donald verdient " +
donald.getGehalt() + " EUR.");
}
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 15
C# 1.01
Reservierte Wörter
Fest definierter Name der
Startmethode
class Program
{
static void Main(string[] args)
{
Person donald = new Person();
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
abstract
decimal
float
namespace
return
try
as
default
for
new
sbyte
typeof
base
delegate
foreach
null
sealed
uint
bool
do
goto
object
short
ulong
break
double
if
operator
sizeof
unchecked
byte
else
implicit
out
stackalloc
unsafe
case
enum
in
override
static
ushort
catch
event
int
params
string
using
char
explicit
interface
private
struct
virtual
checked
extern
internal
ref
switch
void
class
false
is
protected
this
volatile
const
finally
lock
public
throw
while
continue
fixed
long
readonly
true
yield
se-rt
Folie 14
7
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 16
8
Operationen
‰ Müssen mit einem Buchstaben beginnen
‰ _ zählt als Buchstabe
‰ Das Präfix @ ist zulässig und ermöglicht die Verwendung von
Schlüsselwörtern als Bezeichner (aus stilistischen Gründen
wird jedoch dringend davon abgeraten)
‰ Dann dürfen beliebige weitere Zeichen folgen
‰ Achtung: keine Schlüsselwörter verwenden
‰ Konventionen:
Ö Klassennamen und Methodennamen werden groß
geschrieben
Ö Attribute werden klein geschrieben
Ö Bei Wortzusammensetzungen wird der erste Buchstabe
des Folgeworts groß geschrieben (z.B. CamelCase)
Ö Lokale Variablen werden klein geschrieben
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Typenübersicht
Belegung (Wertebereich)
Abgebildet auf
sbyte
-27...27-1 (also: -128…127)
System.SByte
short
-215...215-1 (also: -32768…32767)
System.Int16
int
-231...231-1
System.Int32
long
-263...263-1
System.Int64
byte
0...28-1 (also: 0…255)
System.Byte
ushort
0...216-1
System.UInt16
uint
0...232-1
System.UInt32
ulong
0...264-1
System.UInt64
float
+/-3.40282347 * 1038 (32 Bit IEEE 754)
System.Single
double
+/-1.79769313486231570 * 10308 (64 Bit IEEE 754)
System.Double
decimal
128 Bit
System.Decimal
bool
true, false
System.Boolean
char
Unicode Zeichen
System.Char
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
+, -, !, ~, ++, --
Unäre Operatoren: Vorzeichen, logisches Komplement, bitweises Komplement, Inkrement, Dekrement
(typ)
Typ-Konvertierung
*, /, %
Multiplikation, Division, Modulo
+, -
Addition, Subtraktion
<<, >>
Bitweise verschieben
is as
Typ-Prüfung, Typ-Wandlung
<,>, >=, <=, ==, !=
Vergleiche
&
bitweise Und
^
bitweise Exklusives Oder
|
bitweise Oder
&&
logisches Und
||
logisches Oder
?:
Bedingungsoperator
=, *=, /=, %=, +=, -=, <<=, >>=, >>>=,
&=, ^=, |=
Zuweisung
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 19
Spezielle Operatoren
Typ
se-rt
Primäre Operatoren: Klammerung,
Laufzeitinformation, Überlaufprüfung
se-rt
Folie 17
C# 1.01
(x) x.y f(x) a[x] x++ x–- new typeof
sizeof checked unchecked
Operator-Vorrang
Bezeichner
C# 1.01
‰ Inkrement
int a = 10, b;
b = a++; // -> a = 11, b = 10
b = ++a; // -> a = 12, b = 12
‰ Bedingungsoperator
x = bedingung ? wertFallsBedErfuellt : wertFallsBedNichtErfuellt;
Ist gleichbedeutend mit
if(bedingung) {
x = wertFallsBedErfuellt;
} else {
x = wertFallsBedNichtErfuellt;
}
se-rt
Folie 18
9
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 20
10
Kontrollstrukturen: switch
Aufzählungen
‰ Benannte Zahlen-Konstanten, standardmäßig 4 Byte
‰ Fallunterscheidung
enum Farbe
{
rot, blau, gruen // die Werte sind 0, 1, 2
}
switch (programmiersprache)
{
case "C":
Console.WriteLine("Mühsam");
break;
case "C++":
Console.WriteLine("Besser");
break;
case "C#": case "Java":
Console.WriteLine("Noch besser");
break;
case null:
Console.WriteLine("?");
break;
default:
Console.WriteLine("Noch besser");
break;
}
// ...
Farbe f = Farbe.blau;
if(f == Farbe.rot) { ... }
if(f == 1) { ... }
// Achtung: Fehler!
enum Jahreszeit
{
fruehling=1, sommer = 5, herbst = 12, winter = 20
}
‰ Die case-Marken müssen
von einem break
beendet werden
‰ Als Ausdruck im switch
und den case-Marken
können Integer, enum
und string-Typen
verwendet werden
‰ wird ein expliziter case
nicht gefunden, wird der
default-Block
eingesprungen
enum Status : byte { on, off }
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 21
Kontrollstrukturen: if
Folie 23
‰ Schleifen: for, while, do-while
for(int i = 0; i < 10; i++) {
// ...
}
...
if(a > 20) {
// ...
} else {
// ...
}
int j = 0;
while(j < 10) {
j++;
// ...
}
‰ Der if-Ausdruck muss vom Typ bool sein
‰ Der else-Teil kann entfallen
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Kontrollstrukturen: Schleifen
‰ if-Anweisung
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
‰ break: Ablauf abbrechen
und nach dem (innersten)
Strukturende fortsetzen
‰ continue: Ablauf
abbrechen und mit
nächstem Schleifenwert
fortsetzen
int k = 0;
do {
k++;
// ...
} while(k < 10);
se-rt
Folie 22
11
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 24
12
Kontrollstrukturen: foreach
int[] primzahlen = { 1, 3, 5, 7, 11 };
foreach (int x in primzahlen)
{
Console.WriteLine(x);
}
string abc = "abcdefghijklmnopqr";
foreach (char z in abc)
{
Console.WriteLine(z);
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Referenzparameter
int x = 15;
Console.WriteLine("x=" + x);
test(ref x);
Console.WriteLine("x=" + x);
string text = "Hallo";
test(ref text);
Console.WriteLine("text=" + text);
Schleife
für Kollektionen
‰ Arrays, Strings sowie
alle Klassen, die das
Interface
IEnumerable
implementieren
‰
"Bequeme"
C# 1.01
x=15
i=15
i=99
x=99
text=Kaffee
private static void test(ref int i)
{
Console.WriteLine("i=" + i);
i = 99;
Console.WriteLine("i=" + i);
}
private static void test(ref string s)
{
s = "Kaffee";
}
se-rt
Folie 25
Arrays
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 27
Out-Parameter
‰ out verhält sich wie ref als call by reference, es sind aber auch
uninitialisierte Übergaben zulässig
‰ Ein- oder mehrdimensionale Felder
‰ Index beginnt bei 0
int[] a;
int[] b = new int[5];
int[] c = new int[] { 7, 11, 99 };
int[] d = { 7, 11, 99 };
// Kurzform
Person familieDuck[] = new Person[5]; // 5 Personenreferenzen
string text1;
string text2;
test(out text1, out text2);
Console.WriteLine("text1=" + text1);
Console.WriteLine("text2=" + text2);
// Hilfsfunktionen zur Arraybehandlung in der Klasse Array:
Array.copy(d, a, 2); // kopiert d[0…1] nach a
private static void test(out string s1, out string s2)
{
s1 = "Kaffee";
s2 = "Tasse";
text1=Kaffee
}
text2=Tasse
int[][] e = new int[2][]; // 2 Zeilen, undef. Anzahl Spalten
e[0] = { 1, 3, 5, 7 };
// Zeile 0 hat 4 Spalten
e[0] = { 11, 13, 17, 19, 21 }; // Zeile 1 hat 5 Spalten
int[,] f = new int[2, 3];
// "rechteckiges" Array
int[,] g = { 1, 2, 3 }, { 4, 5, 6}};
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 26
13
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 28
14
Variable Parameterliste
partial class
‰ Der letzte Parameter einer Parameterliste kann als Array deklariert
werden.
‰ Es kann dann eine beliebige Menge an Einzelwerten übergeben
werden.
‰ Dieser Parameter muss mit dem Schlüsselwort params
gekennzeichnet werden
‰ Eine Klasse kann auf mehrere Dateien aufgesplittet werden.
Datei1.cs
namespace BusinessObject
{
partial class Person
{
// ... erster Teil ...
}
}
int ergebnis;
summe(ergebnis, 1, 3, 6, 8, 9, 12, 8);
Console.WriteLine("ergebnis=" + ergebnis);
Datei2.cs
namespace BusinessObject
{
partial class Person
{
// ... zweiter Teil ...
}
}
private static void summe(out int ergebnis, params int[] werte)
{
ergebnis = 0;
foreach (int i in werte) ergebnis += i;
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 29
Namensräume
Folie 31
‰ Wenn bei arithmetischen Operationen der Wertebereich
überschritten wird, tritt kein Fehler auf.
int x = 1000000; // 10 hoch 7
Alternativ zu „using“ kann der
vollqualifizierte Name verwendet
werden:
y=-727379968
int y = x * x;
Console.WriteLine("y=" + y);
‰ Abhilfe: der Operator checked
Namensbereich1.B b = ...
int x = 1000000; // 10 hoch 7
namespace MeinProjekt
{
using Namensbereich1;
class Program
{
A a;
// ...
}
}
se-rt
C# 1.01
Zahlenüberlauf
‰ Namensräume fassen mehrere Klassen, Structs, Interfaces,
Enumerationen und Delegates zu einer logischen Einheit
zusammen
namespace Namensbereich1
{
class A { … }
class B { … }
}
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
checked
{
int y = x * x;
Console.WriteLine("y=" + x);
}
Unbehandelte Ausnahme:
System.OverflowException:
Die arithmetische Operation
hat einen Überlauf
verursacht.
Die Überlaufprüfung kann auch über Compiler-Einstellungen ein/ausgeschaltet werden
C# 1.01
se-rt
Folie 30
15
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 32
16
Zeiger – unsafe und fixed
String
‰ Innerhalb von unsafe-Methoden oder Code-Bereichen können
Zeigeroperationen ausgeführt werden
class UnsafeTest {
unsafe static void quadrat(int* p)
{
*p *= *p;
}
unsafe static void Main() {
int i = 5;
quadrat(&i);
Console.WriteLine(i);
}
}
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
// angenommen, x ist
// ein Attribut von p
unsafe
{
fixed (int* b = &p.x)
{
*b = 99;
// ...
}
}
string s1 = "Kaffee";
string s2 = "tasse";
string s3 = s1 + s2;
Console.WriteLine(s3);
Console.WriteLine(s3.ToUpper());
Console.WriteLine(s3.IndexOf(s2));
Console.WriteLine(s3[7]);
Über das Schlüsselwort
fixed wird der Garbage
Collector angewiesen,
referenzierten Speicher
(z.B. von Arrays oder
Objekt-Attributen) nicht
freizugeben.
Der Gültigkeitsbereich des
nicht sicheren Kontexts reicht
von der Parameterliste bis zum
Methodenende, sodass auch
in der Parameterliste Zeiger
verwendet werden können
se-rt
‰ Der Datentyp zur Zeichenkettenbehandlung ist string
‰ Die string-Methoden (z.B. Insert, Remove, usw.) sind
unverändernd, d.h. der Empfängerstring ändert sich nicht.
Veränderbare Strings ÆStringBuilder
C# 1.01
Ausgabe:
Kaffeetasse
KAFFEETASSE
6
A
string s4 = s3.Insert(6, "unter");
Kaffeetasse
Kaffeeuntertasse
Console.WriteLine(s3);
Console.WriteLine(s4);
se-rt
Folie 33
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 35
Datum
‰ Datum wird durch die Klasse DateTime behandelt
‰ Der Abstand zwischen zwei DateTime-Objekten ist ein Objekt der
Klasse TimeSpan
Kapitel 3: C# Basisklassen
‰
‰
‰
‰
se-rt
DateTime heute = DateTime.Now;
DateTime weihnachten2009 = new DateTime(2009, 12, 24, 12, 0, 0);
Console.WriteLine(heute.ToString("dd.MM.yyyy HH:mm"));
Console.WriteLine(weihnachten2009.ToString("d"));
Console.WriteLine(weihnachten2009.ToString("D"));
String
Datum
Arrays
Einfache Datei Ein-/Ausgabe
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
TimeSpan ts = weihnachten2009 - heute;
Console.WriteLine("Tage bis Weihnachten:" + ts.Days);
Ausgabe:
se-rt
C# 1.01
17
30.09.2009 16:08
24.12.2009
Donnerstag, 24. Dezember 2009
Tage bis Weihnachten:84
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 36
18
Konsolen-Ausgabe
Textdatei schreiben
‰ Console.Write(x)
‰ Console.WriteLine(x)
FileStream fs = new FileStream(
"C:\\Daten\\Quadrate.txt",
FileMode.Create);
StreamWriter writer = new StreamWriter(fs);
‰ Console.WriteLine("{0}, {1}", a, b)
‰ Platzhalter-Syntax
"{"
writer.WriteLine("Quadratzahlen");
for (int i = 0; i < 20; i++)
{
writer.WriteLine("i={0} i*i={1}", i, i * i);
}
writer.Close();
fs.Close();
n ["," width] [":" format [precision] "}"
Ö n: Argumentnummer
Ö width: Feldbreite (positiv: rechtsbündig, negativ: linksbündig)
Ö format (d: Dezimalformat, f: Fixpunktformat, c:
Währungsformat, …)
Ö precision: Anzahl Nachkommastellen
double d1 = 3.149;
Console.WriteLine("{0,2:f2}", d1);
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
3,15
se-rt
Folie 37
C# 1.01
Tastatur-Eingabe
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Folie 39
C# 1.01
Textdatei lesen
‰ Console.Read() Æ liefert als int die Zeichen
‰ Console.ReadLine() Æliefert die Eingabe als string
string eingabe;
do
{
eingabe = Console.ReadLine();
Console.WriteLine("Ihre Eingabe:"
+ eingabe);
} while (eingabe != "Ende");
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
FileStream fr = new FileStream(
"C:\\Daten\\Quadrate.txt",
FileMode.Open);
StreamReader reader = new StreamReader(fr);
string zeile;
while((zeile = reader.ReadLine()) != null)
{
Console.WriteLine(zeile);
}
reader.Close();
fr.Close();
Hallo
Ihre Eingabe:Hallo
Test
Ihre Eingabe:Test
Ende
Ihre Eingabe:Ende
C# 1.01
se-rt
Folie 38
19
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Quadratzahlen
i=0 i*i=0
i=1 i*i=1
i=2 i*i=4
i=3 i*i=9
i=4 i*i=16
i=5 i*i=25
i=6 i*i=36
i=7 i*i=49
i=8 i*i=64
i=9 i*i=81
...
Folie 40
20
Sichtbarkeiten
public
Öffentlich – Zugriff generell möglich
private
Privat – Zugriff nur von Objekten der selben
Klasse
Kapitel 4: C# Klassen
‰
‰
‰
‰
‰
‰
‰
se-rt
Attribute ohne Sichtbarkeitsangabe sind
private
Sichtbarkeiten
Attribute, Methoden
Properties
Konstruktor, Destruktor
Klassenmethoden und –attribute
Operatorenüberladung
structs
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Beispiel: Klasse „Person“ in C#
internal
Wie public, aber auf das „Assembly“
beschränkt
class Person
{
protected double gehalt;
Attribute
Methoden
public void gehaltErhoehen() {
// es gibt für alle 100 EUR mehr
gehalt = gehalt + 100;
}
// ...
se-rt
Folie 43
donald.Gehalt = 1000;
double wert = donald.Gehalt;
// ...
}
}
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
public double Gehalt
{ // ein "Property"
set
{
Console.WriteLine("Set");
gehalt = value;
}
get
{
Console.WriteLine("Get");
return gehalt;
}
}
public double getGehalt() {
return gehalt;
}
public void setGehalt(double g) {
gehalt = g;
}
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Properties
Klassendefinition
protected string name;
protected double gehalt;
protected int alter;
Wie private, aber zusätzlich ist der Zugriff von
Kindklassen möglich
se-rt
C# 1.01
class Person {
protected
C# 1.01
se-rt
Folie 42
21
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 44
22
Destruktor
Methodenüberladung
‰ Methoden mit gleichem Bezeichner können mit unterschiedlicher Signatur
„überladen“ werden (overloading)
‰ Beispiel:
public void
{ // ...
}
public void
{ // ...
}
public void
{ // ...
}
public void
{ // ...
}
se-rt
‰ Der Destruktor bildet das Gegenstück zum Konstruktor, der
Aufrufzeitpunkt ist aber nicht vorhersehbar
‰ Der Destruktor hat den Namen wie die Klasse mit ~ (genau wie in
C++)
‰ Destruktoren sind parameterlos und ohne spezifizierte Sichtbarkeit
‰ Aber Achtung: der Aufrufzeitpunkt in unspezifiziert!
‰ Im Gegensatz zu C++ sind bei C# Destruktoren meist unnötig
print()
print(int anzahl)
print(string infoText)
‰ Eine Ergänzung zum Destruktor bildet das Interface IDisposable
Ö Es muss in der Implementierung die Methode Dispose
implementiert werden
Ö Üblicherweise erfolgt der Aufruf vom Destruktor aus
print(int anzahl, string infoText)
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 45
Konstruktor
‰ Klassenvariablen werden je Klasse einmal angelegt
‰ Klassenmethoden werden über den Klassenbezeichner
aufgerufen: Person.getAnzahlPersonen()
Person donald = new Person("Donald", 45, 400);
Person daisy = new Person();
// ...
class Person
{
private static int anzahlPersonen;
class Person {
// ...
public Person() : this("nobody", 0, 0)
{ // ...
}
public Person(string n, int a, double g)
{
name = n;
alter = a;
gehalt = g;
}
}
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Folie 47
C# 1.01
Klassenmethoden und -variablen
‰ Der Konstruktor wird beim Erzeugen eines Objekts aufgerufen
‰ Kontruktoren können überladen werden
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
public static int getAnzahlPersonen()
{
return anzahlPersonen;
}
Attribut anzahlPersonen
wird von allen
Objekten der Klasse
Person geteilt.
public Person() {
anzahlPersonen ++;
// ...
}
}
se-rt
Folie 46
23
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 48
24
Klassen und Instanzen
‰ Klassenattribut: Alle Objekte
einer Klasse teilen sich das
eine Attribut
Überladene Operatoren
‰ Die arithmetischen Operatoren (+, -, *, /, …) sowie die
Vergleichsoperatoren (==, !=, >, …) können für eine Klasse
überladen werden
‰ Der Methodenname ergibt sich aus „operator“ und dem
Operatorzeichen (z. B. „operator+“)
‰ Die Methode muss public static definiert werden
‰ Instanzattribut: Jedes Objekt
besitzt physisch ein eigenes
Attribut
class Person {
// ...
private static int anzahlPersonen;
// ...
};
class Person {
// ...
private int alter;
// ...
}
‰ Klassenmethode: Aufruf erfolgt
über den Klassennamen:
Person.getAnzahlPersonen()
‰ Instanzmethode: Aufruf erfolgt
über den Objektbezeicher:
wert = donald.getAlter();
class Person {
// ...
public static int getAnzahlPers();
// ...
}
class Person {
// ...
public int getAlter();
// ...
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Ö Unäre Operatoren haben einen Übergabeparameter
Ö Binäre Operatoren haben zwei Übergabeparameter
se-rt
Folie 49
Statischer Konstruktor
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 51
Beispiel: Klasse „Bruch“
‰ Dient der Initialisierung von Klassenattributen
‰ Hat keine Parameter
class Bruch
{
private int zaehler;
private int nenner;
‰ Achtung: es wird keine Reihenfolge beim Aufruf der statischen
Konstruktoren garantiert
public Bruch() : this (0, 1) { }
public Bruch(int z, int n) { zaehler = z; nenner = n; }
class Person {
// ...
static Person()
{
anzahlPersonen = 0;
}
// ...
};
public static Bruch operator+(Bruch a, Bruch b)
{
return new Bruch(a.zaehler * b.nenner + b.zaehler * a.nenner,
a.nenner * b.nenner);
}
public void print() { Console.WriteLine(zaehler+"/"+nenner); }
}
‰ Hinweis: Klassenattribute – wie alle Attribute - werden
standardmäßig mit 0 initialisiert
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 50
25
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 52
26
Typwandlung
Eingebettete Klassen
‰ Eine Typwandlung eines Referenztyps nach int, double oder in
einen anderen Referenztyp kann über einen überladenen castOperator erfolgen
‰ Dieser cast kann „explizit“ oder „implizit“ erfolgen:
class A
{
public void a()
{
Console.WriteLine("a");
B b = new B();
b.b();
}
Bruch a = ...
Bruch b = a + 2; // impliziter cast der "2" (ein int) in Bruch
A a1 = new A();
a.a();
A.B b = new B.C(); // Fehler!
A.C c = new A.C(); // OK
c.c();
class B // nicht öffentlich: nur innerhalb A sichtbar
{
public void b() { Console.WriteLine("b"); }
}
double c = (double)b; // expliziter cast des Bruch b in double
String d = (string)b; // expliziter cast des Bruch b in string
public class C // öffentlich: als A.C auch außerhalb von A sichtbar
{
public void c() { Console.WriteLine("c"); }
}
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 53
Typwandlung
Folie 55
‰ Statische Klassen können nur statische Attribute oder Methoden
haben
class Bruch
{ // ...
public static implicit operator Bruch(int x) // int Æ Bruch
{
return new Bruch(x, 1);
}
public static explicit operator double(Bruch b) // Bruch Æ double
{
return ((double)b.zaehler) / b.nenner;
}
public static explicit operator string(Bruch b) // Bruch Æ string
{
return b.zaehler + "/" + b.nenner;
}
}
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Statische Klassen
‰ Eine Typwandlung erfolgt durch überladene cast-Operatoren
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
static class Konstanten
{
public static const double dmInEuro = 1.95583;
public static const double mwstSatz = 0.19;
static double nachEuro(double dm) {
return dmInEuro * dm;
}
}
se-rt
Folie 54
27
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 56
28
structs
Vererbung
‰ structs sind Werttypen
‰ Zuweisungen zwischen structs kopieren die Attribute (und nicht die
Objektreferenz!)
struct Punkt
{
public int m_x;
public int m_y;
Person
name
alter
gehalt
Punkt p1 = new Punkt(1, 1);
Punkt p2;
p2 = p1;
p2.print();
p1.m_x = 99;
P1.print();
p2.print();
public Punkt(int x, int y)
{
m_x = x;
Ein
m_y = y;
Ein
}
Ein
public void print()
{
Console.WriteLine("Ein Punkt x={0}
}
gehaltErhoehen
Punkt x=1 y=1
Punkt x=99 y=1
Punkt x=1 y=1
Programmierer
firmenWagen
progSprache
y={1}", m_x, m_y);
Manager
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 57
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Spezialisierung
Ö Die Kindklassen
„Programmierer“ und
„Manager“ werden von
der Klasse „Person“
abgeleitet - sind
Spezialisierungen der
Klasse „Person“
Generalsierung
Ö Die Gemeinsamkeiten von
„Programmierer“ und
„Manager“ werden in der
Vaterklasse „Person“
vereinigt – „Person“ ist
Generalisierung von
„Programmierer“ und
„Manager“
C# 1.01
Folie 59
Vererbung
‰ A subclass may inherit the structure and behavior of its
superclass.
Kapitel 4: Vererbung
‰
‰
‰
‰
‰
‰
se-rt
Prinzip
Laufzeitbindung
Überschreiben und verdecken
Abstrakte Klassen
Interface
Die Klasse Object
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
se-rt
C# 1.01
29
Quelle: Booch, Grady, Object-Oriented Analysis and Design with Applications, 1991
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 60
30
Polymorphismus
UML-Darstellung
Person
gehaltErhoehen()
Überschreiben und Verdecken
‰ Laufzeitbindung einer Methode muss ausdrücklich über virtual
festgelegt werden.
‰ Methoden können in Kindklassen mit
selbem Namen erneut implementiert
‰ Damit entsteht unterschiedliches
Verhalten, die öffentliche Struktur bleibt
gleich
‰ Die Objekte können sich autonom
verhalten
class Person
{
public virtual void gehaltErhoehen()
{
gehalt = gehalt + 100;
}
}
Programmierer
Person p = ...
p.gehaltErhoehen();
Bindung erfolgt dynamisch
gehaltErhoehen()
‰ In einer Kindklasse kann eine Methode definiert werden als
Ö new: Vaterklassenimplementierung wird „verdeckt“; keine
Laufzeitbindung
Ö override: Vaterklassenimplementierung wird überschrieben,
Laufzeitbindung (virtual) erforderlich
C#-Code
class Person
{
public void gehaltErhoehen()
{
gehalt = gehalt + 100;
}
}
se-rt
class Programmierer : Person
{
public new void gehaltErhoehen() {
gehalt = gehalt * 2;
}
}
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 61
Folie 63
‰ Überschreibende (override) oder verdeckende (new) Methoden
müssen dieselbe Signatur haben wie die entsprechende Methode
der Vaterklasse
Ö Gleiche Typen
Ö Gleiche Parameterzahl
Ö Gleiche Parameterart (ref, out)
Ö Gleiche Sichtbarkeit
‰ In einer override/new-Methode kann die Implementierung der
Vaterklasse aufgerufen werden:
C#-Code
Person donald = new Person();
Programmierer trick = new Programmierer();
donald.setGehalt(1000);
trick.setGehalt(1000);
Console.WriteLine("Donald verdient " + donald.getGehalt() + " EUR.");
Console.WriteLine("Trick verdient " + trick.getGehalt() + " EUR.");
donald.gehaltErhoehen();
trick.gehaltErhoehen();
Console.WriteLine("Donald verdient " + donald.getGehalt() + " EUR.");
Console.WriteLine("Trick verdient " + trick.getGehalt() + " EUR.");
class Programmierer
{
public override void gehaltErhoehen()
{
base.gehaltErhoehen();
// ...
}
}
Ausgabe:
Donald verdient 1000 EUR.
Trick verdient 1000 EUR.
Donald verdient 1100 EUR.
Trick verdient 2000 EUR.
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
override/new/base
Beispiel: Polymorphie
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 62
31
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 64
32
Verdecken bei statischen Methoden
Bildung von Vererbung
‰ Statische Methoden - diese kennen ja keine dynamische Bindung –
können nicht überschrieben (override) werden. Verdecken (new)
ist aber möglich.
1
SachVersicherungsVertrag
‰
‰
SachVersicherungsVertrag
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 65
Statische vs. dynamische Bindung
VersicherungsVertrag
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
‰
Eine weitere Klasse nutzt die
zuvor stattgefundene
Generalisierung
Dieser Vorgang wird nun als
Spezialisierung bezeichnet
SachVersicherungsVertrag
LebenVersicherungsVertrag
JahresBeitrag
VersicherterGegenstand
RisikoLVAnteil
BegünstigtePerson
Laufzeit
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Folie 67
C# 1.01
‰ Realisierung einer "ist-ein" Beziehung im Gegensatz zu einer
"hat-ein" Beziehung der Assoziation
Ö Ein LV-Vertrag ist ein Versicherungsvertrag
Ö Ein Auto hat Räder
‰ Vererbung im fachlichen Kontext ist selten sinnvoll
‰ Alternative zur Vererbung ist eine Aggregation
Person p = new Programmierer()
p.m();
Bindung erfolgt statisch, es wird
die Implementierung des Typs
von p aufgerufen. D.h. es wird m
von Person aufgerufen!
‰ Dynamische Bindung
class Person
{
public virtual void m() { ... }
}
class Programmierer
{
public override void m() { ... }
}
‰
Es wird eine
mögliche Wiederverwendbarkeit
erkennbar
Allgemeingültige
Merkmale werden
generalisiert
Vererbung vs. Aggregation
‰ Statische Bindung
class Person
{
public void m() { ... }
}
class Programmierer
{
public new void m() { ... }
}
‰
VersicherungsNehmer
AbschlussDatum
JahresBeitrag
VersicherterGegenstand
VersicherungsNehmer
AbschlußDatum
se-rt
VersicherungsNehmer
AbschlussDatum
‰
Zunächst entsteht aus den
bekannten Anforderungen eine
konkrete Klasse.
Motivation zur Vererbung besteht
nicht
3
VersicherungsVertrag
2
VersicherungsNehmer
AbschlussDatum
JahresBeitrag
VersicherterGegenstand
A
Person
B
Person p = new Programmierer()
Person
p.m();
Student
Bindung erfolgt dynamisch. Es
wird m von Programmierer
aufgerufen!
C# 1.01
se-rt
Folie 66
33
0..1
Student
‰ Ein Student ist eine Person (?)
‰ Wie wird mit dem Studenten in (A) verfahren, wenn das Studium beendet wurde?
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 68
34
Vererbung abstrakter Methoden
„Versiegelte“ Klassen und Methoden
‰ Von versiegelten (sealed) Klassen können keine Kindklassen
abgeleitet werden
‰ Versiegelte Methoden können nicht überschrieben oder verdeckt
werden
‰ Wird eine abstrakte Methode vererbt, wird deren
Implementierung in den Kindklassen erzwungen
‰ Vorteil: lässt sich auch keine generische Implementierung
festlegen, so ist doch ein gemeinsames Interface erzwingbar
‰
PersistentesObjekt
‰
Die Klasse Person
implementiert
die abstrakte
Methode
Store()
getStoreSQL() : String
Person
getStoreSQL() : String
se-rt
‰
VersicherungsVertrag
class Konto
{
public double getSaldo() { ... }
public sealed Person getInhaber(); // kann nicht über// schrieben werden
Eine abstrakte
Methode erzwingt
die Implementierung
in den Kindklassen
Klassen mit
abstrakten
Methoden können
selbst keine Objekte
instanzieren
}
sealed class GiroKonto : Konto // kann nicht abgeleitet
{
// werden
// …
}
getStoreSQL() : String
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 69
‰ Abstrakte Methoden definieren eine Schnittstelle, die
Implementierung bleibt den Kindklassen überlassen
‰ Eine abstrakte Klasse besteht aus mind. einer abstrakten Methode
sowie weiteren (konkreten) Methoden und Attributen
‰ Abstrakte Methoden werden dynamisch gebunden
C# 1.01
Folie 71
‰ System.Object oder object ist die implizite Vaterklasse aller Klassen
class Object
{
public Type GetType { ... }
public virtual bool Equals(object o) { ... }
public virtual string ToString() { ... }
public virtual int GetHashCode() { ... }
protected object MemberwiseClone() { ... }
...
}
abstract class PersistentObject
{
public int createUniqueID() { ... }
public abstract Result store();
public virtual bool beginTransaction() { ... };
abstract void commit();
abstract void rollback();
}
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Die Klasse Object
Abstrakte Klassen und Methoden
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Object o = new Person();
Person p = o;
// nicht OK!
Person p = (Person)o;
// OK
se-rt
Folie 70
35
// OK
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 72
36
Interface
Typwandlungen - casts
‰ Die Typwandlung über den cast-Operator wirft eine
InvalidCastException falls die Typwandlung nicht möglich ist
‰ Methoden oder Properties in Interfaces sind „automatisch“ public,
abstract und virtual
‰ Der Interface-Name steht als „normaler“ Datentyp zur Verfügung
1
Programmierer p = (Programmierer)donald;
interface IPerson
{
double Gehalt { set; get; }
void gehaltErhoehen();
void print();
}
class Person : IPerson { ... }
Person donald = ...
if(donald is Programmierer)
{
}
Programmierer p = donald as Programmierer;
IPerson donald = new Person();
IPerson trick = new Programmierer();
...
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
2
if (p == null)
{
Console.WriteLine("Donald ist kein Programmierer");
}
se-rt
Folie 73
C# 1.01
Interface
Label-Darstellung:
hatPlaetzeFrei()
einbuchen()
Store()
Delete()
Load()
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 75
Die Klasse Object
‰ Alle Klassen (alle selbstgeschriebenen und alle Klassen der .NET
Bibliothek) sind Kindklassen der Klasse object (bzw. System.Object)
‰ Ein Interface ist einer Klasse mit ausschließlich abstrakten
Methoden gleichzusetzen
‰ Interfaces werden „implementiert"
‰ Eine Klasse kann viele Interfaces implementieren
‰ Interfaces definieren Methoden, die von den
Implementierungen implementiert werden müssen
Veranstaltung
datumVon : Date
datumBis : Date
bezeichnung : String
preis : Waehrungsbetrag
Person donald = ...
class Object
{
public Type GetType() { ... }
public virtual bool Equals(object o) { ... }
public virtual string ToString() { ... }
public virtual int GetHashCode() { ... }
protected object MemberwiseClone() { ... }
...
}
Icon-Darstellung:
<<Interface>>
PersistentesObjekt
Store()
Delete()
Load()
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Veranstaltung
datumVon : Date
datumBis : Date
bezeichnung : String
preis : Waehrungsbetrag
hatPlaetzeFrei()
einbuchen()
Store()
Delete()
Load()
C# 1.01
PersistentesObjek
t
Store()
Delete()
Load()
se-rt
Folie 74
37
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 76
38
Objektkopie
Exceptions
‰ Die protected-Methode MemberWiseClone() von object dient
dem Erstellen von (flachen) Kopien eines Objekts
‰ Alle Attribute werden dabei umkopiert
‰ Dienen zur Fehlerbehandlung
‰ In C# (und den meisten anderen OO-Sprachen) werden
Fehler, die innerhalb einer Methode auftreten, durch eine
Exception dem Aufrufer mitgeteilt
‰ Tritt in einer Methode ein Fehler auf, wird dieser „geworfen“
(throw). Der Aufrufer der Methode „fängt“ (catch) den Fehler
public class Person
{
public Person Clone()
{
return ((Person)MemberwiseClone());
}
// ...
}
‰ Fehler werden schließlich in einem separaten „catch“-Block
behandelt. Hierdurch entsteht eine Trennung von
„produktivem“ Programmcode und der Fehlerbehandlung
Person p1 = ...
Person p2 = p1.Clone();
‰ Falls Beziehungen mit kopiert werden aollen, kann alternativ auch
das Interface ICloneable implementiert werden; in der Methode
public object Clone() muss dann das neue Objekt selbst
generiert und zurückgeliefert werden
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 77
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 79
Exceptions - throw
‰ Beispiel: Das Werfen der Exception
Kapitel 5
Ausnahmen und
Schablonen
void setGehalt(double g)
{
if(g > 1000) {
throw new VerdientZuVielException(g);
}
Standardmäßig
erfolgt der
„Stack-Trace“,
wenn eine
Exception nicht
gefangen wird
// hier geht’s "Normal" weiter
gehalt = g;
‰ Ausnahmen - Exceptions
‰ Generische Klassen - template
}
Unbehandelte Ausnahme: Person1.Program+VerdientZuVielException:
Die Person verdient zu viel: 1200
bei Program.Person.setGehalt(Double g) in Program.cs:Zeile 71.
bei Program.Main(String[] args) in Program.cs:Zeile 27.
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
se-rt
C# 1.01
39
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 80
40
„Eigene“ Exception-Klassen
Beispiel: Exception in .NET Framework
‰ Exception-Klassen müssen von der Klasse Exception oder
ApplicationException ableiten
class VerdientZuVielException : Exception
{
private double betrag;
try
{
FileStream s = new FileStream("personen.dat", FileMode.Open);
IFormatter f = new BinaryFormatter();
personen = f.Deserialize(s) as List<Person>;
s.Close();
// ...
}
catch (IOException ex)
{
MessageBox.Show(ex.Message, "Fehler beim Datenzugriff",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
public VerdientZuVielException() {}
public VerdientZuVielException(double b) { betrag = b; }
public double getBetrag() { return betrag; }
public override string Message
{
get { return "Die Person verdient zu viel: " + getBetrag(); }
}
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 81
Exceptions fangen
Folie 83
‰ Das „potentielle“ Werfen einer Exception muss in C# nicht in der
Methodensignatur angekündigt werden
‰ Der Compiler fordert auch keinen try-catch um einen
Codebereich, der potentiell Exceptions werfen kann
try
{
trick.setGehalt(1200);
// ...
}
catch(VerdientZuVielException vzve)
{
Console.WriteLine("So viel darf er nicht verdienen: "
+ vzve.getBetrag());
// oder:
Console.WriteLine(vzve.Message);
}
catch(Exception e)
{
Console.WriteLine("Hier ist was Schlimmes passiert: " + e.Message);
}
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Bemerkungen zu Exceptions
Person trick;
// ...
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 82
41
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 84
42
template
template Beispiel „Stack“ (2)
‰ Template-Klassen (Schablonenklassen, Generische Klassen,
Generics) sind Klassen, die zur Compilezeit in Teilen parametrisiert
werden können
‰ Templates werden besonders häufig bei Kollektionen verwendet
‰ Beispiel:
Ö Liste<Person> personenListe;
Ö Liste<int> intListe
Ö Stack<String> einStringStack;
‰ Klassen werden zur Kompilezeit „instanziert“; Liste<Person> ist
eine andere Klasse als Liste<int>
Stack<Person> leute = new Stack<Person>();
leute.push(donald);
leute.push(trick);
leute.push(track);
leute.push(tick);
leute.push(daisy);
Console.WriteLine(leute.pop().ToString());
Console.WriteLine(leute.pop().ToString());
Console.WriteLine(leute.pop().ToString());
Console.WriteLine(leute.pop().ToString());
Console.WriteLine(leute.pop().ToString());
Daisy
Tick
Track
Trick
Donald
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
se-rt
Folie 85
C# 1.01
template Beispiel „Stack“ (1)
7
7
7
7
45
Jahre
Jahre
Jahre
Jahre
Jahre
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
alt,
alt,
alt,
alt,
alt,
300,00
200,00
400,00
1100,00
1100,00
EUR
EUR
EUR
EUR
EUR
C# 1.01
Gehalt
Gehalt
Gehalt
Gehalt
Gehalt
Folie 87
Vererbung bei templates (1)
‰ Template-Klasse wird Kindklasse einer „normalen“ Klasse
class Stack<Element>
{
private Element[] speicherbereich;
private int stackEnde = 0;
public Stack()
{
speicherbereich = new Element[10];
}
public void push(Element e)
{
speicherbereich[stackEnde] = e;
stackEnde++;
}
public Element pop()
{
Element e = speicherbereich[stackEnde - 1];
stackEnde--;
return e;
}
public int size() { return stackEnde; }
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Stack
<
Person
>
leute;
class List
{
public int size() { ... }
};
class Stack<Element> : List
{
// ...
}
se-rt
Folie 86
43
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 88
44
Vererbung bei templates (2)
Delegates
‰ Template-Klasse wird Kindklasse einer Template-Klasse
‰ Ein „delegate“ (Æ Delegierter, Vertreter) „vertritt“ einen
Methodenaufruf
‰ Über das Schlüsselwort delegate wird ein Delegate-Datentyp
definiert – zu beachten ist die Signatrur!
‰ Von diesem Datentyp werden Objekte erzeugt, die im Konstruktor
den Methodenaufruf erhalten
class List<Element> {
protected Element[] speicherbereich;
};
class Stack<Element> : List<Element>
{
// ...
delegate void IchVertrete(); // der Datentyp der Vertreters
}
IchVertrete donaldDrucktSich = new IchVertrete(donald.print);
IchVertrete daisyDrucktSich = new IchVertrete(daisy.print);
// …
donaldDrucktSich();
daisyDrucktSich();
Dieser Typ kann auch konkret
festgelegt werden (z.B.
Object)
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 89
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 91
Multicast-Delegates
‰ Ein einziger Delegate kann gleich mehrere Methodenaufrufe
zugewiesen bekommen
Kapitel 6
Delegates und Attribute
‰
‰
‰
‰
‰
se-rt
IchVertreteWas druckAktion = new IchVertreteWas(donald.print);
druckAktion += new IchVertreteWas(daisy.print);
//
druckAktion();
Vertreter - delegate
Events
Threads
Attribute
Reflektion
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
// führt beide print-Methoden aus
‰ Kurzschriebweise
IchVertreteWas druckAktion = donald.print;
//
druckAktion();
se-rt
C# 1.01
45
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 92
46
Events
Anonyme Methoden
‰ Events sind lokal in einer Klasse gekapselte Vertreter
‰ Übung: ein „flexibler“ Rechner
delegate void AenderungsInfo(string senderInfo);
class PersonenView1
{
public PersonenView1(Person p) { p.aenderungsInfo += Anzeige; }
public void Anzeige(string text)
{ Console.WriteLine("View1: " + text); }
}
Rechner r = new Rechner();
int[] zahlen = { 1, 2, 3, 4, 5};
int a = r.rechne(r.bildeSumme, zahlen);
int b = r.rechne(r.bildeMax, zahlen);
int resultat = 1;
r.rechne(delegate(int x) { resultat *= x; }, zahlen);
PersonenView1 view1 = new PersonenView1(donald);
donald.gehaltErhoehen();
class Person {
public event AenderungsInfo aenderungsInfo;
// ...
public void gehaltErhoehen()
{ // ...
aenderungsInfo(this.ToString());
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 93
Beispiel delegate (1)
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Folie 95
C# 1.01
Threads
‰ Übung: ein „flexibler“ Rechner
‰ using System.Threading
Person donald = new Person("Donald", 45, 1000);
delegate void Rechnen(int i);
class Rechner
{
public int erg = 0;
public void bildeSumme(int i) { erg += i; }
public void bildeMax(int i) { erg = i > erg ? i : erg; }
Thread t = new Thread(new ThreadStart(donald.print));
t.Start(); // Æ ruft donald.print auf
Thread.Sleep(100); // 100ms den aktuellen Thread anhalten
public int rechne(Rechnen rechnen, int[] zahlen)
{
erg = 0;
foreach(int i in zahlen) { rechnen(i); }
return erg;
}
Delegate
‰ Synchronisation
}
lock(object)
{
// ...
}
Rechner r = new Rechner();
int[] zahlen = { 1, 2, 3, 4, 5};
int a = r.rechne(r.bildeSumme, zahlen);
int b = r.rechne(r.bildeMax, zahlen);
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 94
47
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 96
48
Synchronisation
Attribute auswerten
‰ Attribute können auch zur Laufzeit ausgewertet werden
Person donald = new Person("Donald", 45, 1000);
Thread t1 = new Thread(new ThreadStart(donald.zaehleLangsam));
Thread t2 = new Thread(new ThreadStart(donald.zaehleLangsam));
t1.Start();
t2.Start();
// ...
Type t = typeof(AltesDing);
object[] attributes =
t.GetCustomAttributes(typeof(VeraltetAttribute), true);
class Person { // ...
private int counter = 0;
public void zaehleLangsam() {
for (int i = 0; i < 100; i++) {
lock (this) {
int tmp = counter;
Thread.Sleep(100);
counter = tmp + 1;
Console.WriteLine("counter=" + counter);
}
}
}
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
foreach (object o in attributes)
{
if (o is VeraltetAttribute)
{
Console.WriteLine(((VeraltetAttribute)attributes[0]).Message);
}
}
// ...
se-rt
Folie 97
Attribute
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 99
Attribut DllImport
‰ Der extern-Modifizierer wird verwendet, um eine extern
implementierte Methode zu deklarieren.
‰ Methoden mit dem Attribut „DllImport“ werden über die InteropServices behandelt
‰ C#-Sprachelemente, wie z.B. Klassen, Methoden oder Attribute
können attributiert werden (Java-Bezeichnung: Annotation)
‰ Attribute werden in [..] vor das betreffende Sprachelement
geschrieben
[Veraltet("Bitte nicht mehr verwenden")]
class AltesDing
{ // ...
}
using System.Runtime.InteropServices
class Test
{
[DllImport("user32.dll")]
public static extern int MessageBox(int hParent, string text,
string caption, int type);
public sealed class VeraltetAttribute : Attribute
{
string message;
public string Message { get { return message; } }
public VeraltetAttribute(string m) { message = m; }
}
public static void Anzeige()
{
MessageBox(0, "Hallo von C#", "Eine Messagebox", 1);
}
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 98
49
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 100
50
Attribut: Serializable
Kommentare zur Dokumentation
‰ Objekte von Klassen mit dem Attribut [Serializable] können in einen
Datenstrom z.B. in eine Datei serialisiert werden
‰ Attribute, die nicht gespeichert werden sollen, werden als
[NonSerialized] attributiert
/// <summary>
/// natürliche Personen gem. Spezifikation Kapitel 4
/// </summary>
class Person : IPerson
{
[Serializable]
class Person
{
[NonSerialized] private static int anzahlPersonen = 0;
protected string name;
protected int alter;
protected double gehalt;
// ...
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 101
Attribut: Serializable
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 103
Reflektion
‰ Unter Reflektion wird der Zugriff auf Klasseneigenschaften, Methoden und
Attribute verstanden
‰ System.Reflection
‰ Beispiel: der Aufruf einer Methode
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
Person donald = …
Object o = donald;
Type type = o.GetType();
MethodInfo diePrintMethode = type.GetMethod("gehaltErhoehen");
// Objekt in Datei schreiben
FileStream s = new FileStream("duck.dat", FileMode.Create);
IFormatter f = new BinaryFormatter();
f.Serialize(s, donald);
s.Close();
diePrintMethode.Invoke(o, new object[0]); // Methodenaufruf
// Objekt aus Datei lesen
FileStream s = new FileStream("duck.dat", FileMode.Open);
IFormatter f = new BinaryFormatter();
Person ps = f.Deserialize(s) as Person;
s.Close();
Bei überladenen Methoden (Methoden mit dem gleichen Namen und
unterschiedlicher Parameterliste) wird die GetMethods()-Methode von
Type verwendet und über die MethodInfo-Objekte wird die gesuchte
Methode ausgewählt.
‰ Praktischer sind Collection-Klassen, die sich selbst und ihre
enthaltenen Elemente serialisieren (z.B. List<T>)
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 102
51
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 104
52
Kapitel 6
.NET Klassenbibliothek
Kapitel 7
Kollektionen
‰ Übersicht
se-rt
‰
‰
‰
‰
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
se-rt
C# 1.01
Klassenbibliothek
UI
HtmlControls
Discovery
WebControls
System.Windows.Forms
Design
Protocols
C# 1.01
‰ Klassen, die das Interface IEnumerable implementieren, können
wie eine Kollektion behandelt werden.
‰ yield Æeinbringen trägt zu einer Kollektion bei
ComponentModel
System.Drawing
Caching
Security
Drawing2D
Printing
Configuration
SessionState
Imaging
Text
System.Data
public class Wochentage : System.Collections.IEnumerable
{
public System.Collections.IEnumerator GetEnumerator()
{
yield return "Sonntag";
yield return "Montag";
yield return "Dienstag";
yield return "Mittwoch";
yield return "Donnerstag";
yield return "Freitag";
yield return "Samstag";
}
}
System.Xml
ADO
SQL
XSLT
Design
SQLTypes
XPath
Serialization
System
Collections
IO
Security
Configuration
Net
ServiceProcess
Diagnostics
Reflection
Text
Remoting
Globalization
Resources
Threading
Serialization
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Das Interface IEnumerable
System.Web
Services
Description
Iteratoren - IEnumerable
Indexer
ICollection
ICollection<T>
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Runtime
InteropServices
se-rt
Folie 106
53
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 108
54
Das Interface IEnumerable
Collection-Typen
‰ Beispiel: Verwendung in einer foreach-Schleife
ICollection
int Count
void CopyTo(Array a, int pos)
IEnumerator GetEnumerator()
…
Wochentage wochentage = new Wochentage();
foreach (string wochentag in wochentage)
{
Console.WriteLine(wochentag);
}
IList
object this[int index]
void Clear()
int Add(obejct o)
…
IDictionary
ICollection Keys
ICollection Values
void Add(object key, object value)
…
ArrayList
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 109
Der Indexer
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Hashtable
C# 1.01
Folie 111
Klasse ArrayList
‰ Zugriffsmöglichkeit über den Index-Operator
‰ Es können get und set implementiert werden
‰ Standard-Klasse für Array-Funktionen
Wochentage wochentage = new Wochentage();
Console.WriteLine(wochentage[3]);
ArrayList familieDuck = new ArrayList();
familieDuck.Add(donald);
familieDuck.Insert(0, daisy);
familieDuck.Add(trick);
familieDuck.Add(track);
familieDuck.Insert(1, tick);
public class Wochentage : ...
{
string[] wochentage = { "Sonntag", "Montag",
"Dienstag", "Mittwoch", "Donnerstag",
"Freitag", "Samstag" };
foreach (object o in familieDuck)
{
Console.WriteLine(o.ToString());
}
public string this[int index]
{
get { return wochentage[index]; }
}
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 110
55
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 112
56
Klasse Hashtable
Klasse List<T>
‰ Implementiert eine Schlüssel-Wert-Beziehung
‰ Standard-Klasse für Array-Funktionen
Hashtable woerterbuch = new Hashtable();
woerterbuch.Add("rot", "red");
woerterbuch.Add("blau", "blue");
woerterbuch.Add("schwarz", "black");
woerterbuch.Add("gelb", "yellow");
List<Person> familieDuck = new List<Person>();
familieDuck.Add(donald);
familieDuck.Insert(0, daisy);
familieDuck.Add(trick);
familieDuck.Add(track);
familieDuck.Insert(1, tick);
Console.WriteLine(woerterbuch["rot"]);
foreach (Person p in familieDuck)
{
p.gehaltErhoehen();
Console.WriteLine(p.ToString());
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 113
Generische Collection-Typen
List<T>
se-rt
Folie 115
‰ Dictionary (System.Collections.Generic)
ICollection<T>
T this[int index]
void Clear()
Int Add(T o)
…
C# 1.01
Klasse Dictionary<TKey, TValue>
int Count
void CopyTo(Array a, int pos)
IEnumerator GetEnumerator()
…
IList<T>
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Dictionary<string, Person> namensTabelle =
new Dictionary<string, Person>();
namensTabelle["Donald"] = donald;
namensTabelle["Tick"] = tick;
namensTabelle["Trick"] = trick;
namensTabelle["Track"] = track;
IDictionary<TKey, TVal>
if(namensTabelle.ContainsKey("Donald"))
{
Console.WriteLine(namensTabelle["Donald"].ToString());
}
ICollection<TKey> Keys
ICollection<TVal> Values
void Add(TKey key, TVal value)
…
Dictionary<TKey, TVal>
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 114
57
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 116
58
Beispiel: Interface IComparable
Übung: Windows-Forms-Applikation
‰ Personen-Objekte laden und speichern (via Serialisierung)
‰ Erfassung mit Name, Alter, Gehalt
‰ Anzeige der Liste in einer Listbox
‰ Die Methode int CompareTo(object obj) muss implementiert
werden
‰ Kollektionen können nun sehr einfach sortiert werden
public class Person : IComparable
{
// wenn this > obj --> 1
// wenn this < obj --> -1
// wenn this == obj --> 0
public int CompareTo(object obj)
{
Person p = (Person)obj;
if (this.gehalt > p.gehalt)
return 1;
if (this.gehalt < p.gehalt)
return -1;
else
return 0;
List<Person> familieDuck =
new List<Person>();
familieDuck.Add(donald);
// ...
familieDuck.Sort();
foreach (Person p in familieDuck)
{
p.print();
}
// oder:
Person[] liste = …
Array.Sort(liste);
}
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 117
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 119
Formular und Formularelemente
‰ Der Dialog wird durch eine Kindklasse
von Form gebildet
‰ Je Formularelement gibt es ein Attribut
mit definierten Eigenschaften
Kapitel 8
Beispiel: Windows-Forms
public partial class PersonenForm : Form
{
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.editName = new System.Windows.Forms.TextBox();
// ...
}
‰ Form
‰ Formularelemente
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox editName;
private System.Windows.Forms.NumericUpDown editAlter;
// ...
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
se-rt
C# 1.01
59
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 120
60
Eigenschaften der Formular-Elemente
‰ Properties
‰ Events
Subjekt und Listen-Modell
Selektion des
Formular-Elements
‰ Das aktuell bearbeitete Personen-Objekt wird zum „Subjekt“
‰ Die Liste der Personen-Objekte wird in einem vom Formularelement
getrennten Modell - einer List<Person> - gespeichert
public partial class PersonenForm : Form
{
private List<Person> personen = new List<Person>();
private Person subjekt = null;
// ...
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 121
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 123
Subjekt lesen und anzeigen
‰ Personen-Objekt-Inhalte lesen und anzeigen
private void showSubject()
{
editName.Text = subjekt.getName();
editAlter.Value = subjekt.getAlter();
editGehalt.Text = String.Format("{0:c}", subjekt.getGehalt());
}
Kapitel 9: Unit-Test
private void readSubject()
{
string name = editName.Text;
int alter = (int)editAlter.Value;
string gehaltText = editGehalt.Text;
double gehalt = (double)Decimal.Parse(gehaltText);
‰ Übersicht
‰ Testprojekt
‰ Testklasse und Testattribute
subjekt.setName(name);
subjekt.setAlter(alter);
subjekt.setGehalt(gehalt);
}
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 122
61
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
62
Teststufen - Übersicht
Unit-Test (1)
‰ Testgegenstand sind Komponenten, teilintegrierte Systeme oder
Systeme
‰ „Testen im Kleinen“ (Liggesmeyer)
‰ Das Testobjekt beim Unit-Test ist eine Unit (=Komponente, Modul,
Subsystem). Komponenten sind ein Teil einer Applikation, z. B. eine
(oder mehrere) Klassen oder eine Prozedur.
‰ Im Unit-Test wird die „Unit“ gegen die Spezifikation getestet. Dazu
ist eine Unit-Spezifikation erforderlich!
‰ Die Unit sollte möglichst isoliert getestet werden; die Isolierung hat
dabei den Zweck, Unit-externe Einflüsse beim Test auszuschließen.
‰ Die Zuständigkeit für Unit-Tests liegt in der Regel in der Entwicklung
(und nicht in der Testabteilung!)
‰ Unit-Test, Komponententest, Modultest
Ö „autarke“ Komponenten werden isoliert
getestet
‰ Integrationstest
Ö Teilintegrierte Komponenten testen die
Komponenteninteraktion
‰ Systemtest
Ö Test des Gesamtsystems
se-rt
se-rt
Bilder: Martin Glinz, Universität Zürich
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 125
Teststufen
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 127
Unit-Test (2)
‰ Unit-Test
‰ Integrationstest
‰ Systemtest
‰ Die Schnittstelle einer Unit ist in der Regel eine
Programmierschnittstelle. D.h., die Ausführung der Testfälle wird
in der Regel in der Programmiersprache des Moduls
programmiert.
‰ Wird ein Fehler gefunden, lässt sich die Ursache in der Regel
der getesteten Unit zuordnen.
‰ Es stehen Frameworks zur Verfügung: Visual Studio,
www.junit.org, www.testng.org, CppUnit, TESSY, Rational Test
Realtime
‰ Parametrisierte Testfälle können mit Daten aus einer externen
Datenquelle befüllt werden
‰ Weitere Teststufen
Ö User Acceptance Test (UAT)
Ö Beta-Test
Ö Abnahmetest
Ö Deployment-Test
‰ Test gegen nichtfunktionale Anforderungen
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 126
63
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 128
64
Testaufbau
Beispiel: Testmethoden für Bruch
‰ Beispiel Testmethoden
Testtreiber
[TestMethod]
public void TestAddiere()
{
Bruch b1 = new Bruch(1, 2);
Bruch b2 = new Bruch(1, 3);
Bruch b3 = new Bruch(5, 6);
Bruch b4 = b1 + b2;
Assert.AreEqual(b3, b4);
}
[TestMethod]
public void TestKehrwert()
{
Bruch b1 = new Bruch(1, 2);
Bruch b2 = new Bruch(2, 1);
Bruch b3 = !b2;
Assert.AreEqual(b1, b3);
}
Der Testtreiber startet die Ausführung
des Prüflings und nimmt Resultate
entgegen
Prüfling
Stub
se-rt
Ein Stub (Platzhalter) ersetzt eine vom
Prüfling genutzte Funktion
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 129
Unit-Test mit Visual Studio
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
Ausgangssituation
Aktion
Resultatsvergleich
Ausgangssituation
Aktion
Resultatsvergleich
C# 1.01
Folie 131
Unit-Test Attribute
‰ Es wird ein Test-Projekt angelegt; das Projekt mit den zu testenden
Klassen wird „referenziert“ (Hinweis: die zu testenden Klassen
müssen dort public sein)
‰ [ClassInitialize]
Ö Wird vor Ausführung des ersten Testfalls [TestMethod]
aufgerufen. Es können Initialisierungen vor Beginn des Tests
vorgenommen werden.
‰ [ClassCleanup]
Ö Aufräumarbeiten nach Ende aller Testfälle [TestMethod]
‰ [TestInitialize]
Ö Initialisierung, die vor jedem einzelnen Testfall [TestMethod]
aufgerufen werden
‰ [TestCleanup]
‰ Testklassen und Testmethoden werden über Attribute gesteuert
‰ Es ist oft hilfreich, wenn die zu testende Klasse eine EqualsMethode implementiert hat
[TestClass]
public class UnitTestBruch
{
[TestMethod]
public void TestInit()
{
Bruch b = new Bruch(1, 2);
Assert.AreEqual((double)b, 0.5, "Fehler beim Initialisieren");
}
}
Ö Aufräumarbeiten, die nach jedem einzelnen Testfall
[TestMethod] aufgerufen werden
‰ [TestMethod]
Ö Ein Testfall
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 130
65
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 132
66
Entwurfskriterium: Testbarkeit
‰ Die Isolierbarkeit einer Unit ist eine Voraussetzung für Unit-Tests
‰ Isolierbare Units entstehen bei Entwurf nicht zwangsläufig – die
Isolierbarkeit muss aktiv im Entwurf herbeigeführt werden
‰ Empfehlung: Testbarkeit sollte bei Entwurfsreviews mit einbezogen
werden
‰ Zur Resultatsprüfung sind oftmals spezielle Diagnose-Methoden im
Prüfling erforderlich; d.h. der Unit-Test hinterläßt durchaus seine
„Spuren“ an der zu testenden Unit.
Einführung in die
Programmiersprache C#
Rainer Schmidberger
[email protected]
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
se-rt
Folie 133
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Test-First-Ansatz
‰ Es werden zuerst die Testfälle (in der Regel eingebettet in den
Testtreiber) implementiert und anschließend der produktive
Programmcode
‰ Test-First entstammt den agilen Vorgehensweisen (Extreme
Programming)
‰ Vorteile
Ö QS der Anforderung
Ö Automatisierung spart Aufwand
Ö Der Test verliert den negativen Beigeschmack
Ö Testfälle werden dokumentiert und sind reproduzierbar
‰ In der Praxis stellt eine unvollständige Unit-Spezifikation ein großes
Problem dar!
se-rt
www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH
C# 1.01
Folie 134
67
68