c# folien 101 - iste.uni- · pdf fileeine klasse, die in c# geschrieben ist, kann von einer...
TRANSCRIPT
1
se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Einführung in die Programmiersprache C#
Rainer [email protected]
se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Kapitel 1: C# Übersicht
Entwicklung bis heuteKonzepteArchitektur
2
Folie 3se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
C# und .NET: die Entwicklung
.NET 3.5 und Visual Studio 2008 werden veröffentlichtNovember 2007
.NET 3.0 wird veröffentlichNovember 2006
.NET 2.0 und Visual Studio 2005 werden veröffentlichtNovember 2005
.NET 1.1und Visual Studio 2003 werden veröffentlichtApril 2003
.NET 1.0 und Visual Studio .NET 2002 werden veröffentlichtJanuar 2002
C# wird zur Standardisierung eingereichtOktober 2000
Bill Gates stellt erstmals die .NET-„Vision“ vor.Juni 2000
EreignisDatum
Folie 4se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
.NET: Framework, Sprachen und Werkzeuge
Base Class Library
Common Language Specification
Common Language Runtime
Data and XML
VB C++ C#
Visu
al Stu
dio
.NE
T
WebServices
JScript …
UserInterface
Quelle: Microsoft
3
Folie 5se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
.NET FrameworkDas .NET Framework umfasst:
Laufzeitumgebung: Common Language Runtime (CLR) mit einer für alle .NET gemeinsamen Common IntermediateLanguage (CIL). Z.B. ist der Garbage Collector in der CLR implementiertTypsystem: Common Language Specification (CLS)undCommon 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.
Folie 6se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
.NET Framework: ein SprachenmixEine .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 inVisual 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.
4
Folie 7se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Common Intermediate LanguageDie CIL ist der „Befehlssatz“ der Virtual Machine von .NET
D.h. .NET-Anwendungen sind plattform-unabhängig in CIL geschriebenDer CIL-Code sichert die kompatibilität zwischen den verschiedenen .NET ProgrammiersprachenCIL ist eine „objektorientierte Assemblersprache“
Folie 8se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Common Language Runtime
C++/CLI nimmt Sonderstellung ein: wird (meistens) direkt in Maschinencode compiliert (d.h. CIL wird nicht verwendet)
5
Folie 9se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Common Language Runtime
Class Loader
IL to NativeCompilers
CodeManager
GarbageCollector
Security Engine Debug Engine
Type Checker Exception Manager
Thread Support COM Marshaler
Quelle: Microsoft
Folie 10se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Architektur des .NET Framework
.NET Programmiersprachen
Ein gemeinsames Typsystem für alle .NET Sprachen
Umfangreiche Klassen-Bibliothek
Laufzeitumgebung
Quelle: Microsoft
6
Folie 11se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01 Quelle: Microsoft
se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Kapitel 2: C# Grundlagen
Kommentare, Bezeichner, reservierte WörterTypenübersichtOperationenArraysKontrollstrukturen
7
Folie 13se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Einfaches BeispielC#-CodeUML-Darstellung
class Person {private double gehalt;
public double getGehalt() {return gehalt;
}
public void setGehalt(int g) {gehalt = g;
}
public void gehaltErhoehen() {gehalt = gehalt + 100;
}}
Person.cs
Person
gehalt: double
gehaltErhoehen()setGehaltgetGehalt
Folie 14se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Testrahmen für die Klasse Person
class Program{static void Main(string[] args){Person donald = new Person();
donald.setGehalt(1000);
Console.WriteLine("Donald verdient " + donald.getGehalt() + " EUR.");
donald.gehaltErhoehen();
Console.WriteLine("Donald verdient " + donald.getGehalt() + " EUR.");
}}
Fest definierter Name der Startmethode
PersonTest.cs
8
Folie 15se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
KommentareKommentierter Bereich/* Dies ist ein Kommentar,der über mehrereZeilen verläuft */
Zeilenkommentarint x = 1; // Anfangswert// ab jetzt folgen Initialisierungen
Folie 16se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Reservierte Wörter
true
throw
this
switch
struct
string
static
stackalloc
sizeof
short
sealed
sbyte
return
voidrefinternalexternchecked
uintnullforeachdelegatebase
readonly
public
protected
private
params
override
out
operator
object
new
namespace
yieldlongfixedcontinue
whilelockfinallyconst
volatileisfalseclass
virtualinterfaceexplicitchar
usinginteventcatch
ushortinenumcase
unsafeimplicitelsebyte
uncheckedifdoublebreak
ulonggotodobool
typeoffordefaultas
tryfloatdecimalabstract
9
Folie 17se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
BezeichnerMüssen mit einem Buchstaben beginnen_ zählt als BuchstabeDas 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 folgenAchtung: keine Schlüsselwörter verwenden
Konventionen:Klassennamen und Methodennamen werden großgeschriebenAttribute werden klein geschriebenBei Wortzusammensetzungen wird der erste Buchstabe des Folgeworts groß geschrieben (z.B. CamelCase)Lokale Variablen werden klein geschrieben
Folie 18se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Typenübersicht
System.Booleantrue, falsebool
System.Double+/-1.79769313486231570 * 10308 (64 Bit IEEE 754)double
System.Single+/-3.40282347 * 1038 (32 Bit IEEE 754)float
System.UInt160...216-1ushort
System.Byte0...28-1 (also: 0…255)byte
System.UInt640...264-1ulong
System.UInt320...232-1uint
Unicode Zeichen
128 Bit
-263...263-1
-231...231-1
-215...215-1 (also: -32768…32767)
-27...27-1 (also: -128…127)
Belegung (Wertebereich)
System.Charchar
System.Decimaldecimal
System.Int64long
System.Int32int
System.Int16short
System.SBytesbyte
Abgebildet aufTyp
10
Folie 19se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Operationen
Zuweisung=, *=, /=, %=, +=, -=, <<=, >>=, >>>=, &=, ^=, |=
Bedingungsoperator? :
logisches Oder||
logisches Und&&
bitweise Oder|
bitweise Exklusives Oder^
bitweise Und&
Vergleiche<,>, >=, <=, ==, !=
Typ-Prüfung, Typ-Wandlungis as
Bitweise verschieben<<, >>
Addition, Subtraktion+, -
Multiplikation, Division, Modulo*, /, %
Typ-Konvertierung(typ)
Unäre Operatoren: Vorzeichen, logisches Komple-ment, bitweises Komplement, Inkrement, Dekrement
+, -, !, ~, ++, --
Primäre Operatoren: Klammerung, Laufzeitinformation, Überlaufprüfung
(x) x.y f(x) a[x] x++ x–- new typeofsizeof checked unchecked
Op
era
tor-
Vo
rra
ng
Folie 20se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Spezielle OperatorenInkrement
int a = 10, b;
b = a++; // -> a = 11, b = 10b = ++a; // -> a = 12, b = 12
Bedingungsoperatorx = bedingung ? wertFallsBedErfuellt : wertFallsBedNichtErfuellt;
if(bedingung) {x = wertFallsBedErfuellt;
} else {x = wertFallsBedNichtErfuellt;
}
Ist gleichbedeutend mit
11
Folie 21se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
AufzählungenBenannte Zahlen-Konstanten, standardmäßig 4 Byte
enum Farbe{
rot, blau, gruen // die Werte sind 0, 1, 2}
// ...Farbe f = Farbe.blau;
if(f == Farbe.rot) { ... }if(f == 1) { ... } // Achtung: Fehler!
enum Jahreszeit{
fruehling=1, sommer = 5, herbst = 12, winter = 20}
enum Status : byte { on, off }
Folie 22se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Kontrollstrukturen: ifif-Anweisung
...if(a > 20) {
// ...} else {
// ...}
Der if-Ausdruck muss vom Typ bool seinDer else-Teil kann entfallen
12
Folie 23se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Kontrollstrukturen: switchFallunterscheidung
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;
}
Die case-Marken müssenvon einem breakbeendet werdenAls Ausdruck im switchund den case-Markenkönnen Integer, enumund string-Typenverwendet werdenwird ein expliziter casenicht gefunden, wird der default-Block eingesprungen
Folie 24se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Kontrollstrukturen: SchleifenSchleifen: for, while, do-while
for(int i = 0; i < 10; i++) {// ...
}
int j = 0;while(j < 10) {
j++;// ...
}
int k = 0;do {
k++;// ...
} while(k < 10);
break: Ablauf abbrechen und nach dem (innersten) Strukturende fortsetzencontinue: Ablauf abbrechen und mit nächstem Schleifenwert fortsetzen
13
Folie 25se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
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);}
"Bequeme" Schleife für KollektionenArrays, Strings sowie alle Klassen, die das Interface IEnumerableimplementieren
Folie 26se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
ArraysEin- oder mehrdimensionale FelderIndex beginnt bei 0
int[] a;int[] b = new int[5];int[] c = new int[] { 7, 11, 99 };int[] d = { 7, 11, 99 }; // KurzformPerson familieDuck[] = new Person[5]; // 5 Personenreferenzen
// Hilfsfunktionen zur Arraybehandlung in der Klasse Array:Array.copy(d, a, 2); // kopiert d[0…1] nach a
int[][] e = new int[2][]; // 2 Zeilen, undef. Anzahl Spaltene[0] = { 1, 3, 5, 7 }; // Zeile 0 hat 4 Spaltene[0] = { 11, 13, 17, 19, 21 }; // Zeile 1 hat 5 Spalten
int[,] f = new int[2, 3]; // "rechteckiges" Arrayint[,] g = { 1, 2, 3 }, { 4, 5, 6}};
14
Folie 27se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Referenzparameterint x = 15;Console.WriteLine("x=" + x);test(ref x);Console.WriteLine("x=" + x);string text = "Hallo";test(ref text);Console.WriteLine("text=" + text);
x=15i=15i=99x=99text=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";}
Folie 28se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Out-Parameter
string text1;string text2;test(out text1, out text2);Console.WriteLine("text1=" + text1);Console.WriteLine("text2=" + text2);
private static void test(out string s1, out string s2){
s1 = "Kaffee";s2 = "Tasse";
}
out verhält sich wie ref als call by reference, es sind aber auch uninitialisierte Übergaben zulässig
text1=Kaffeetext2=Tasse
15
Folie 29se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Variable ParameterlisteDer 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 paramsgekennzeichnet werden
int ergebnis;summe(ergebnis, 1, 3, 6, 8, 9, 12, 8);Console.WriteLine("ergebnis=" + ergebnis);
private static void summe(out int ergebnis, params int[] werte){
ergebnis = 0;foreach (int i in werte) ergebnis += i;
}
Folie 30se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
NamensräumeNamensräume fassen mehrere Klassen, Structs, Interfaces, Enumerationen und Delegates zu einer logischen Einheit zusammen
namespace Namensbereich1{
class A { … }class B { … }
}
namespace MeinProjekt{
using Namensbereich1;class Program{
A a;// ...
}}
Alternativ zu „using“ kann der vollqualifizierte Name verwendet werden:
Namensbereich1.B b = ...
16
Folie 31se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
partial classEine Klasse kann auf mehrere Dateien aufgesplittet werden.
namespace BusinessObject{
partial class Person {
// ... erster Teil ...}
}
namespace BusinessObject{
partial class Person {
// ... zweiter Teil ...}
}
Datei1.cs
Datei2.cs
Folie 32se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Zahlenüberlauf
int x = 1000000; // 10 hoch 7
int y = x * x;Console.WriteLine("y=" + y);
Wenn bei arithmetischen Operationen der Wertebereich überschritten wird, tritt kein Fehler auf.
Abhilfe: der Operator checked
y=-727379968
int x = 1000000; // 10 hoch 7
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
17
Folie 33se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Zeiger – unsafe und fixed
// angenommen, x ist // ein Attribut von punsafe{
fixed (int* b = &p.x){
*b = 99;// ...
}}
Innerhalb von unsafe-Methoden oder Code-Bereichen können Zeigeroperationen ausgeführt werden
Der Gültigkeitsbereich des nicht sicheren Kontexts reicht von der Parameterliste bis zum Methodenende, sodass auch in der Parameterliste Zeiger verwendet werden können
class UnsafeTest {unsafe static void quadrat(int* p){
*p *= *p;}unsafe static void Main() {
int i = 5;quadrat(&i);Console.WriteLine(i);
}}
Über das Schlüsselwort fixed wird der GarbageCollector angewiesen, referenzierten Speicher (z.B. von Arrays oder Objekt-Attributen) nicht freizugeben.
se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Kapitel 3: C# Basisklassen
StringDatumArraysEinfache Datei Ein-/Ausgabe
18
Folie 35se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
StringDer Datentyp zur Zeichenkettenbehandlung ist stringDie string-Methoden (z.B. Insert, Remove, usw.) sind unverändernd, d.h. der Empfängerstring ändert sich nicht. Veränderbare Strings StringBuilder
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]);
string s4 = s3.Insert(6, "unter");
Console.WriteLine(s3);Console.WriteLine(s4);
KaffeetasseKAFFEETASSE6A
KaffeetasseKaffeeuntertasse
Ausgabe:
Folie 36se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
DatumDatum wird durch die Klasse DateTime behandeltDer Abstand zwischen zwei DateTime-Objekten ist ein Objekt der Klasse TimeSpan
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"));
TimeSpan ts = weihnachten2009 - heute;Console.WriteLine("Tage bis Weihnachten:" + ts.Days);
30.09.2009 16:0824.12.2009Donnerstag, 24. Dezember 2009Tage bis Weihnachten:84
Ausgabe:
19
Folie 37se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Konsolen-AusgabeConsole.Write(x)Console.WriteLine(x)
Console.WriteLine("{0}, {1}", a, b)
Platzhalter-Syntax"{" n ["," width] [":" format [precision] "}"
n: Argumentnummerwidth: 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);
3,15
Folie 38se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Tastatur-EingabeConsole.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");
HalloIhre Eingabe:HalloTestIhre Eingabe:TestEndeIhre Eingabe:Ende
20
Folie 39se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Textdatei schreiben
FileStream fs = new FileStream("C:\\Daten\\Quadrate.txt",
FileMode.Create);StreamWriter writer = new StreamWriter(fs);
writer.WriteLine("Quadratzahlen");for (int i = 0; i < 20; i++){
writer.WriteLine("i={0} i*i={1}", i, i * i);}writer.Close();fs.Close();
Folie 40se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Textdatei lesen
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();
Quadratzahleni=0 i*i=0i=1 i*i=1i=2 i*i=4i=3 i*i=9i=4 i*i=16i=5 i*i=25i=6 i*i=36i=7 i*i=49i=8 i*i=64i=9 i*i=81...
21
se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Kapitel 4: C# Klassen
SichtbarkeitenAttribute, MethodenPropertiesKonstruktor, DestruktorKlassenmethoden und –attributeOperatorenüberladungstructs
Folie 42se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Beispiel: Klasse „Person“ in C#class Person {
protected string name;protected double gehalt;protected int alter;
public double getGehalt() {return gehalt;
}
public void setGehalt(double g) {gehalt = g;
}
public void gehaltErhoehen() {// es gibt für alle 100 EUR mehrgehalt = gehalt + 100;
}// ...
}
Attribute
Methoden
Klassendefinition
22
Folie 43se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Sichtbarkeiten
Wie private, aber zusätzlich ist der Zugriff von Kindklassen möglich
protected
Wie public, aber auf das „Assembly“beschränkt
internal
Privat – Zugriff nur von Objekten der selben Klasse
Attribute ohne Sichtbarkeitsangabe sind private
private
Öffentlich – Zugriff generell möglichpublic
Folie 44se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Propertiesclass Person{
protected double gehalt;
public double Gehalt{ // ein "Property"
set{
Console.WriteLine("Set");gehalt = value;
}get{
Console.WriteLine("Get");return gehalt;
}}
// ...}
donald.Gehalt = 1000;
double wert = donald.Gehalt;
23
Folie 45se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
MethodenüberladungMethoden mit gleichem Bezeichner können mit unterschiedlicher Signatur „überladen“ werden (overloading)Beispiel:
public void print(){ // ...}public void print(int anzahl){ // ...}public void print(string infoText){ // ...}public void print(int anzahl, string infoText){ // ...}
Folie 46se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
KonstruktorDer Konstruktor wird beim Erzeugen eines Objekts aufgerufenKontruktoren können überladen werden
Person donald = new Person("Donald", 45, 400);Person daisy = new Person();// ...
class Person {// ...public Person() : this("nobody", 0, 0) { // ...}public Person(string n, int a, double g){
name = n;alter = a;gehalt = g;
}}
24
Folie 47se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
DestruktorDer Destruktor bildet das Gegenstück zum Konstruktor, der Aufrufzeitpunkt ist aber nicht vorhersehbarDer Destruktor hat den Namen wie die Klasse mit ~ (genau wie in C++)Destruktoren sind parameterlos und ohne spezifizierte SichtbarkeitAber Achtung: der Aufrufzeitpunkt in unspezifiziert!Im Gegensatz zu C++ sind bei C# Destruktoren meist unnötig
Eine Ergänzung zum Destruktor bildet das Interface IDisposableEs muss in der Implementierung die Methode Disposeimplementiert werdenÜblicherweise erfolgt der Aufruf vom Destruktor aus
Folie 48se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Klassenmethoden und -variablenKlassenvariablen werden je Klasse einmal angelegtKlassenmethoden werden über den Klassenbezeichneraufgerufen: Person.getAnzahlPersonen()
class Person {private static int anzahlPersonen;
public static int getAnzahlPersonen(){return anzahlPersonen;
}
public Person() {anzahlPersonen ++;// ...
}}
Attribut anzahlPersonenwird von allen Objekten der Klasse Person geteilt.
25
Folie 49se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Klassen und Instanzen
class Person {// ...private static int anzahlPersonen;// ...
};
class Person {// ...public static int getAnzahlPers();// ...
}
class Person {// ...private int alter;// ...
}
class Person {// ...public int getAlter();// ...
}
Klassenattribut: Alle Objekte einer Klasse teilen sich das eine Attribut
Instanzattribut: Jedes Objekt besitzt physisch ein eigenes Attribut
Klassenmethode: Aufruf erfolgt über den Klassennamen:Person.getAnzahlPersonen()
Instanzmethode: Aufruf erfolgt über den Objektbezeicher:wert = donald.getAlter();
Folie 50se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Statischer KonstruktorDient der Initialisierung von KlassenattributenHat keine Parameter
Achtung: es wird keine Reihenfolge beim Aufruf der statischen Konstruktoren garantiert
Hinweis: Klassenattribute – wie alle Attribute - werden standardmäßig mit 0 initialisiert
class Person {// ...static Person() {anzahlPersonen = 0;
}// ...
};
26
Folie 51se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Überladene OperatorenDie arithmetischen Operatoren (+, -, *, /, …) sowie die Vergleichsoperatoren (==, !=, >, …) können für eine Klasse überladen werdenDer Methodenname ergibt sich aus „operator“ und dem Operatorzeichen (z. B. „operator+“)Die Methode muss public static definiert werden
Unäre Operatoren haben einen ÜbergabeparameterBinäre Operatoren haben zwei Übergabeparameter
Folie 52se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Beispiel: Klasse „Bruch“
class Bruch {
private int zaehler;private int nenner;
public Bruch() : this (0, 1) { }public Bruch(int z, int n) { zaehler = z; nenner = n; }
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); }}
27
Folie 53se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
TypwandlungEine Typwandlung eines Referenztyps nach int, double oder in einen anderen Referenztyp kann über einen überladenen cast-Operator erfolgenDieser cast kann „explizit“ oder „implizit“ erfolgen:
Bruch a = ...Bruch b = a + 2; // impliziter cast der "2" (ein int) in Bruch
double c = (double)b; // expliziter cast des Bruch b in double
String d = (string)b; // expliziter cast des Bruch b in string
Folie 54se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
TypwandlungEine Typwandlung erfolgt durch überladene cast-Operatoren
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; }
}
28
Folie 55se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Eingebettete Klassenclass A{
public void a() {
Console.WriteLine("a");B b = new B();b.b();
}
class B // nicht öffentlich: nur innerhalb A sichtbar{
public void b() { Console.WriteLine("b"); }}
public class C // öffentlich: als A.C auch außerhalb von A sichtbar{
public void c() { Console.WriteLine("c"); }}
}
A a1 = new A();a.a();
A.B b = new B.C(); // Fehler!
A.C c = new A.C(); // OKc.c();
Folie 56se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Statische KlassenStatische Klassen können nur statische Attribute oder Methoden haben
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;
}
}
29
Folie 57se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
structsstructs sind WerttypenZuweisungen zwischen structs kopieren die Attribute (und nicht die Objektreferenz!)
struct Punkt{
public int m_x;public int m_y;
public Punkt(int x, int y){
m_x = x;m_y = y;
}public void print(){
Console.WriteLine("Ein Punkt x={0} y={1}", m_x, m_y);}
}
Ein Punkt x=1 y=1Ein Punkt x=99 y=1Ein Punkt x=1 y=1
Punkt p1 = new Punkt(1, 1);Punkt p2;p2 = p1;p2.print();p1.m_x = 99;P1.print();p2.print();
se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Kapitel 4: Vererbung
PrinzipLaufzeitbindungÜberschreiben und verdeckenAbstrakte KlassenInterfaceDie Klasse Object
30
Folie 59se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Vererbung
SpezialisierungDie Kindklassen „Programmierer“ und „Manager“ werden von der Klasse „Person“abgeleitet - sind Spezialisierungen der Klasse „Person“
GeneralsierungDie Gemeinsamkeiten von „Programmierer“ und „Manager“ werden in der Vaterklasse „Person“vereinigt – „Person“ ist Generalisierung von „Programmierer“ und „Manager“
Person
namealtergehalt
gehaltErhoehen
Programmierer
progSprache
Manager
firmenWagen
Folie 60se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
VererbungA subclass may inherit the structure and behavior of itssuperclass.
Quelle: Booch, Grady, Object-Oriented Analysis and Design with Applications, 1991
31
Folie 61se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
PolymorphismusMethoden können in Kindklassen mit selbem Namen erneut implementiertDamit entsteht unterschiedliches Verhalten, die öffentliche Struktur bleibt gleichDie Objekte können sich autonom verhalten
class Programmierer : Person {public new void gehaltErhoehen() {
gehalt = gehalt * 2;}
}
C#-Code
UML-Darstellung
Person
gehaltErhoehen()
Programmierer
gehaltErhoehen()
class Person {public void gehaltErhoehen() {gehalt = gehalt + 100;
}}
Folie 62se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Beispiel: Polymorphie
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.");
Donald verdient 1000 EUR.Trick verdient 1000 EUR.Donald verdient 1100 EUR.Trick verdient 2000 EUR.
C#-Code
Ausgabe:
32
Folie 63se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Überschreiben und VerdeckenLaufzeitbindung einer Methode muss ausdrücklich über virtualfestgelegt werden.
In einer Kindklasse kann eine Methode definiert werden als new: Vaterklassenimplementierung wird „verdeckt“; keine Laufzeitbindungoverride: Vaterklassenimplementierung wird überschrieben, Laufzeitbindung (virtual) erforderlich
class Person {public virtual void gehaltErhoehen() {gehalt = gehalt + 100;
}}
Person p = ...
p.gehaltErhoehen();
Bindung erfolgt dynamisch
Folie 64se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
override/new/baseÜberschreibende (override) oder verdeckende (new) Methoden müssen dieselbe Signatur haben wie die entsprechende Methode der Vaterklasse
Gleiche TypenGleiche ParameterzahlGleiche Parameterart (ref, out)Gleiche Sichtbarkeit
In einer override/new-Methode kann die Implementierung der Vaterklasse aufgerufen werden:
class Programmierer {
public override void gehaltErhoehen() {
base.gehaltErhoehen();// ...
}}
33
Folie 65se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Verdecken bei statischen MethodenStatische Methoden - diese kennen ja keine dynamische Bindung –können nicht überschrieben (override) werden. Verdecken (new) ist aber möglich.
Folie 66se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Statische vs. dynamische BindungStatische Bindung
Dynamische Bindung
class Person {public void m() { ... }}class Programmierer {public new void m() { ... }
}
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!
class Person {public virtual void m() { ... }}class Programmierer {public override void m() { ... }
}
Person p = new Programmierer()
p.m();
Bindung erfolgt dynamisch. Es wird m von Programmierer aufgerufen!
34
Folie 67se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Bildung von Vererbung
VersicherungsNehmerAbschlussDatumJahresBeitragVersicherterGegenstand
SachVersicherungsVertrag1
Zunächst entsteht aus den bekannten Anforderungen eine konkrete Klasse.Motivation zur Vererbung besteht nicht
VersicherungsVertrag
VersicherungsNehmerAbschlußDatum
SachVersicherungsVertrag LebenVersicherungsVertrag
RisikoLVAnteilBegünstigtePersonLaufzeit
3 Eine weitere Klasse nutzt die zuvor stattgefundene GeneralisierungDieser Vorgang wird nun als Spezialisierung bezeichnet
JahresBeitragVersicherterGegenstand
VersicherungsVertrag
VersicherungsNehmerAbschlussDatum
SachVersicherungsVertrag
2
Es wird eine mögliche Wieder-verwendbarkeiterkennbarAllgemeingültige Merkmale werden generalisiert
VersicherungsNehmerAbschlussDatumJahresBeitragVersicherterGegenstand
Folie 68se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Vererbung vs. AggregationRealisierung einer "ist-ein" Beziehung im Gegensatz zu einer "hat-ein" Beziehung der Assoziation
Ein LV-Vertrag ist ein VersicherungsvertragEin Auto hat Räder
Vererbung im fachlichen Kontext ist selten sinnvoll Alternative zur Vererbung ist eine Aggregation
Person
Student
Person Student0..1
A B
Ein Student ist eine Person (?)Wie wird mit dem Studenten in (A) ver-fahren, wenn das Studium beendet wurde?
35
Folie 69se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Vererbung abstrakter MethodenWird eine abstrakte Methode vererbt, wird deren Implementierung in den Kindklassen erzwungenVorteil: lässt sich auch keine generische Implementierung festlegen, so ist doch ein gemeinsames Interface erzwingbar
PersistentesObjekt
Person VersicherungsVertrag
Store()getStoreSQL() : String
getStoreSQL() : String getStoreSQL() : String
Eine abstrakte Methode erzwingt die Implementierung in den KindklassenKlassen mit abstrakten Methoden können selbst keine Objekte instanzieren
Die Klasse Person implementiert die abstrakte Methode
Folie 70se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Abstrakte Klassen und Methoden
abstract class PersistentObject{public int createUniqueID() { ... }public abstract Result store(); public virtual bool beginTransaction() { ... }; abstract void commit(); abstract void rollback();
}
Abstrakte Methoden definieren eine Schnittstelle, die Implementierung bleibt den Kindklassen überlassenEine abstrakte Klasse besteht aus mind. einer abstrakten Methodesowie weiteren (konkreten) Methoden und AttributenAbstrakte Methoden werden dynamisch gebunden
36
Folie 71se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
„Versiegelte“ Klassen und Methoden
class Konto{public double getSaldo() { ... }public sealed Person getInhaber(); // kann nicht über-
// schrieben werden
}sealed class GiroKonto : Konto // kann nicht abgeleitet { // werden// …
}
Von versiegelten (sealed) Klassen können keine Kindklassen abgeleitet werdenVersiegelte Methoden können nicht überschrieben oder verdeckt werden
Folie 72se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Die Klasse ObjectSystem.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() { ... } ...
}
Object o = new Person(); // OK
Person p = o; // nicht OK!Person p = (Person)o; // OK
37
Folie 73se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
InterfaceMethoden oder Properties in Interfaces sind „automatisch“ public, abstract und virtualDer Interface-Name steht als „normaler“ Datentyp zur Verfügung
interface IPerson{double Gehalt { set; get; }void gehaltErhoehen();void print();
}class Person : IPerson { ... }
IPerson donald = new Person();IPerson trick = new Programmierer();...
Folie 74se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
InterfaceEin Interface ist einer Klasse mit ausschließlich abstrakten Methoden gleichzusetzenInterfaces werden „implementiert"Eine Klasse kann viele Interfaces implementierenInterfaces definieren Methoden, die von den Implementierungen implementiert werden müssen
PersistentesObjekt
Store()Delete()Load()
<<Interface>>
Veranstaltung
datumVon : DatedatumBis : Datebezeichnung : Stringpreis : Waehrungsbetrag
hatPlaetzeFrei()einbuchen()Store()Delete()Load()
Veranstaltung
datumVon : DatedatumBis : Datebezeichnung : Stringpreis : Waehrungsbetrag
hatPlaetzeFrei()einbuchen()Store()Delete()Load()
PersistentesObjekt
Store()Delete()Load()
Label-Darstellung: Icon-Darstellung:
38
Folie 75se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Typwandlungen - casts
Person donald = ...
Programmierer p = (Programmierer)donald;
Die Typwandlung über den cast-Operator wirft eine InvalidCastException falls die Typwandlung nicht möglich ist
Person donald = ...
if(donald is Programmierer) {}
Programmierer p = donald as Programmierer;
if (p == null){
Console.WriteLine("Donald ist kein Programmierer");}
1
2
Folie 76se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Die Klasse ObjectAlle Klassen (alle selbstgeschriebenen und alle Klassen der .NETBibliothek) sind Kindklassen der Klasse object (bzw. System.Object)
class Object{
public Type GetType() { ... }public virtual bool Equals(object o) { ... }public virtual string ToString() { ... }public virtual int GetHashCode() { ... }protected object MemberwiseClone() { ... }...
}
39
Folie 77se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
ObjektkopieDie protected-Methode MemberWiseClone() von object dient dem Erstellen von (flachen) Kopien eines ObjektsAlle Attribute werden dabei umkopiert
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
public class Person {public Person Clone(){return ((Person)MemberwiseClone());
}// ...
}
Person p1 = ...Person p2 = p1.Clone();
se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Kapitel 5Ausnahmen und Schablonen
Ausnahmen - ExceptionsGenerische Klassen - template
40
Folie 79se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
ExceptionsDienen zur FehlerbehandlungIn C# (und den meisten anderen OO-Sprachen) werden Fehler, die innerhalb einer Methode auftreten, durch eine Exception dem Aufrufer mitgeteiltTritt in einer Methode ein Fehler auf, wird dieser „geworfen“(throw). Der Aufrufer der Methode „fängt“ (catch) den FehlerFehler werden schließlich in einem separaten „catch“-Block behandelt. Hierdurch entsteht eine Trennung von „produktivem“ Programmcode und der Fehlerbehandlung
Folie 80se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Exceptions - throwBeispiel: Das Werfen der Exception
void setGehalt(double g){
if(g > 1000) {throw new VerdientZuVielException(g);
}
// hier geht’s "Normal" weitergehalt = g;
}
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.
Standardmäßig erfolgt der „Stack-Trace“, wenn eine Exception nicht gefangen wird
41
Folie 81se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
„Eigene“ Exception-KlassenException-Klassen müssen von der Klasse Exception oder ApplicationException ableiten
class VerdientZuVielException : Exception{
private double betrag;
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(); }}
}
Folie 82se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Exceptions fangenPerson trick;// ...
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);}
42
Folie 83se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Beispiel: Exception in .NET Framework
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);
}
Folie 84se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Bemerkungen zu ExceptionsDas „potentielle“ Werfen einer Exception muss in C# nicht in der Methodensignatur angekündigt werdenDer Compiler fordert auch keinen try-catch um einen Codebereich, der potentiell Exceptions werfen kann
43
Folie 85se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
templateTemplate-Klassen (Schablonenklassen, Generische Klassen, Generics) sind Klassen, die zur Compilezeit in Teilen parametrisiert werden könnenTemplates werden besonders häufig bei Kollektionen verwendetBeispiel:
Liste<Person> personenListe;
Liste<int> intListe
Stack<String> einStringStack;Klassen werden zur Kompilezeit „instanziert“; Liste<Person> ist eine andere Klasse als Liste<int>
Folie 86se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
template Beispiel „Stack“ (1)
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; }
}
Stack < Person > leute;
44
Folie 87se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
template Beispiel „Stack“ (2)
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 7 Jahre alt, 300,00 EUR GehaltTick 7 Jahre alt, 200,00 EUR GehaltTrack 7 Jahre alt, 400,00 EUR GehaltTrick 7 Jahre alt, 1100,00 EUR GehaltDonald 45 Jahre alt, 1100,00 EUR Gehalt
Folie 88se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Vererbung bei templates (1)Template-Klasse wird Kindklasse einer „normalen“ Klasse
class List{public int size() { ... }
};
class Stack<Element> : List{// ...
}
45
Folie 89se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Vererbung bei templates (2)Template-Klasse wird Kindklasse einer Template-Klasse
class List<Element> {protected Element[] speicherbereich;
};
class Stack<Element> : List<Element>{// ...
}
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
Kapitel 6Delegates und Attribute
Vertreter - delegateEventsThreadsAttributeReflektion
46
Folie 91se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
DelegatesEin „delegate“ ( Delegierter, Vertreter) „vertritt“ einen MethodenaufrufÜber das Schlüsselwort delegate wird ein Delegate-Datentypdefiniert – zu beachten ist die Signatrur!Von diesem Datentyp werden Objekte erzeugt, die im Konstruktorden Methodenaufruf erhalten
delegate void IchVertrete(); // der Datentyp der Vertreters
IchVertrete donaldDrucktSich = new IchVertrete(donald.print);IchVertrete daisyDrucktSich = new IchVertrete(daisy.print);
// …donaldDrucktSich();daisyDrucktSich();
Folie 92se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Multicast-DelegatesEin einziger Delegate kann gleich mehrere Methodenaufrufe zugewiesen bekommen
Kurzschriebweise
IchVertreteWas druckAktion = new IchVertreteWas(donald.print);druckAktion += new IchVertreteWas(daisy.print);
// druckAktion(); // führt beide print-Methoden aus
IchVertreteWas druckAktion = donald.print;
// druckAktion();
47
Folie 93se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
EventsEvents sind lokal in einer Klasse gekapselte Vertreterdelegate void AenderungsInfo(string senderInfo);class PersonenView1{
public PersonenView1(Person p) { p.aenderungsInfo += Anzeige; }public void Anzeige(string text) { Console.WriteLine("View1: " + text); }
}
PersonenView1 view1 = new PersonenView1(donald);donald.gehaltErhoehen();
class Person {public event AenderungsInfo aenderungsInfo;// ...public void gehaltErhoehen(){ // ...
aenderungsInfo(this.ToString());}
Folie 94se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Beispiel delegate (1)Übung: ein „flexibler“ Rechner
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; }
public int rechne(Rechnen rechnen, int[] zahlen){erg = 0;foreach(int i in zahlen) { rechnen(i); }return erg;
}}
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);
48
Folie 95se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Anonyme MethodenÜbung: ein „flexibler“ Rechner
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);
Folie 96se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Threadsusing System.Threading
Synchronisation
Person donald = new Person("Donald", 45, 1000);
Thread t = new Thread(new ThreadStart(donald.print));
t.Start(); // ruft donald.print auf
Thread.Sleep(100); // 100ms den aktuellen Thread anhalten
lock(object){
// ...}
Delegate
49
Folie 97se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Synchronisation
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();
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);
}}
}}
Folie 98se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
AttributeC#-Sprachelemente, wie z.B. Klassen, Methoden oder Attribute können attributiert werden (Java-Bezeichnung: Annotation)Attribute werden in [..] vor das betreffende Sprachelement geschrieben
public sealed class VeraltetAttribute : Attribute{
string message;public string Message { get { return message; } }public VeraltetAttribute(string m) { message = m; }
}
[Veraltet("Bitte nicht mehr verwenden")]class AltesDing{ // ...}
50
Folie 99se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Attribute auswertenAttribute können auch zur Laufzeit ausgewertet werden
// ...Type t = typeof(AltesDing);object[] attributes = t.GetCustomAttributes(typeof(VeraltetAttribute), true);
foreach (object o in attributes){
if (o is VeraltetAttribute){
Console.WriteLine(((VeraltetAttribute)attributes[0]).Message);}
}// ...
Folie 100se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Attribut DllImportDer extern-Modifizierer wird verwendet, um eine extern implementierte Methode zu deklarieren. Methoden mit dem Attribut „DllImport“ werden über die Interop-Services behandelt
using System.Runtime.InteropServicesclass Test{
[DllImport("user32.dll")]public static extern int MessageBox(int hParent, string text,
string caption, int type);
public static void Anzeige() {
MessageBox(0, "Hallo von C#", "Eine Messagebox", 1);}
}
51
Folie 101se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Attribut: SerializableObjekte von Klassen mit dem Attribut [Serializable] können in einen Datenstrom z.B. in eine Datei serialisiert werdenAttribute, die nicht gespeichert werden sollen, werden als [NonSerialized] attributiert
[Serializable]class Person{
[NonSerialized] private static int anzahlPersonen = 0;protected string name;protected int alter;protected double gehalt;// ...
}
Folie 102se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Attribut: Serializable
Praktischer sind Collection-Klassen, die sich selbst und ihre enthaltenen Elemente serialisieren (z.B. List<T>)
using System.IO;using System.Runtime.Serialization.Formatters.Binary;using System.Runtime.Serialization;
Person donald = …
// Objekt in Datei schreibenFileStream s = new FileStream("duck.dat", FileMode.Create);IFormatter f = new BinaryFormatter();f.Serialize(s, donald);s.Close();
// Objekt aus Datei lesenFileStream s = new FileStream("duck.dat", FileMode.Open);IFormatter f = new BinaryFormatter();Person ps = f.Deserialize(s) as Person;s.Close();
52
Folie 103se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Kommentare zur Dokumentation
/// <summary>/// natürliche Personen gem. Spezifikation Kapitel 4/// </summary>
class Person : IPerson{
Folie 104se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
ReflektionUnter Reflektion wird der Zugriff auf Klasseneigenschaften, Methoden und Attribute verstandenSystem.ReflectionBeispiel: der Aufruf einer Methode
Object o = donald;Type type = o.GetType();MethodInfo diePrintMethode = type.GetMethod("gehaltErhoehen");
diePrintMethode.Invoke(o, new object[0]); // Methodenaufruf
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.
53
se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Kapitel 6.NET Klassenbibliothek
Übersicht
Folie 106se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
System
System.Data System.Xml
System.Web
Globalization
Diagnostics
Configuration
Collections
Resources
Reflection
Net
IO
Threading
Text
ServiceProcess
Security
Design
ADO
SQLTypes
SQL
XPath
XSLT
RuntimeInteropServices
Remoting
Serialization
Serialization
Configuration SessionState
Caching Security
ServicesDescription
Discovery
Protocols
UIHtmlControls
WebControls
System.Drawing
Imaging
Drawing2D
Text
Printing
System.Windows.Forms
Design ComponentModel
Klassenbibliothek
54
se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Kapitel 7Kollektionen
Iteratoren - IEnumerableIndexerICollectionICollection<T>
Folie 108se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Das Interface IEnumerableKlassen, die das Interface IEnumerable implementieren, können wie eine Kollektion behandelt werden.yield einbringen trägt zu einer Kollektion bei
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";
}}
55
Folie 109se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Das Interface IEnumerableBeispiel: Verwendung in einer foreach-Schleife
Wochentage wochentage = new Wochentage();foreach (string wochentag in wochentage){
Console.WriteLine(wochentag);}
Folie 110se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Der IndexerZugriffsmöglichkeit über den Index-OperatorEs können get und set implementiert werden
Wochentage wochentage = new Wochentage();Console.WriteLine(wochentage[3]);
public class Wochentage : ...{
string[] wochentage = { "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag" };
public string this[int index]{
get { return wochentage[index]; }}
}
56
Folie 111se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Collection-TypenICollection
int Countvoid CopyTo(Array a, int pos)IEnumerator GetEnumerator()…
IList
object this[int index]void Clear()int Add(obejct o)…
IDictionary
ICollection KeysICollection Valuesvoid Add(object key, object value)…
ArrayList Hashtable
Folie 112se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Klasse ArrayListStandard-Klasse für Array-Funktionen
ArrayList familieDuck = new ArrayList();familieDuck.Add(donald);familieDuck.Insert(0, daisy);familieDuck.Add(trick);familieDuck.Add(track);familieDuck.Insert(1, tick);
foreach (object o in familieDuck){
Console.WriteLine(o.ToString());}
57
Folie 113se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Klasse HashtableImplementiert eine Schlüssel-Wert-Beziehung
Hashtable woerterbuch = new Hashtable();woerterbuch.Add("rot", "red");woerterbuch.Add("blau", "blue");woerterbuch.Add("schwarz", "black");woerterbuch.Add("gelb", "yellow");
Console.WriteLine(woerterbuch["rot"]);
Folie 114se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Generische Collection-TypenICollection<T>
int Countvoid CopyTo(Array a, int pos)IEnumerator GetEnumerator()…
IList<T>
T this[int index]void Clear()Int Add(T o)…
IDictionary<TKey, TVal>
ICollection<TKey> KeysICollection<TVal> Valuesvoid Add(TKey key, TVal value)…
List<T> Dictionary<TKey, TVal>
58
Folie 115se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Klasse List<T>Standard-Klasse für Array-Funktionen
List<Person> familieDuck = new List<Person>();familieDuck.Add(donald);familieDuck.Insert(0, daisy);familieDuck.Add(trick);familieDuck.Add(track);familieDuck.Insert(1, tick);
foreach (Person p in familieDuck){p.gehaltErhoehen();Console.WriteLine(p.ToString());}
Folie 116se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Klasse Dictionary<TKey, TValue>Dictionary (System.Collections.Generic)
Dictionary<string, Person> namensTabelle = new Dictionary<string, Person>();
namensTabelle["Donald"] = donald;namensTabelle["Tick"] = tick;namensTabelle["Trick"] = trick;namensTabelle["Track"] = track;
if(namensTabelle.ContainsKey("Donald")){
Console.WriteLine(namensTabelle["Donald"].ToString());}
59
Folie 117se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Beispiel: Interface IComparableDie Methode int CompareTo(object obj) muss implementiert werdenKollektionen können nun sehr einfach sortiert werdenpublic class Person : IComparable{// wenn this > obj --> 1// wenn this < obj --> -1// wenn this == obj --> 0public int CompareTo(object obj){Person p = (Person)obj;
if (this.gehalt > p.gehalt)return 1;
if (this.gehalt < p.gehalt)return -1;
elsereturn 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
Kapitel 8Beispiel: Windows-Forms
FormFormularelemente
60
Folie 119se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Übung: Windows-Forms-ApplikationPersonen-Objekte laden und speichern (via Serialisierung)Erfassung mit Name, Alter, GehaltAnzeige der Liste in einer Listbox
Folie 120se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Formular und FormularelementeDer Dialog wird durch eine Kindklasse von Form gebildetJe Formularelement gibt es ein Attribut mit definierten Eigenschaften
public partial class PersonenForm : Form{
private void InitializeComponent(){
this.label1 = new System.Windows.Forms.Label();this.editName = new System.Windows.Forms.TextBox();// ...
}
private System.Windows.Forms.Label label2;private System.Windows.Forms.TextBox editName;private System.Windows.Forms.NumericUpDown editAlter;// ...
}
61
Folie 121se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Eigenschaften der Formular-Elemente
Properties Events
Selektion des Formular-Elements
Folie 122se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Subjekt lesen und anzeigenPersonen-Objekt-Inhalte lesen und anzeigen
private void showSubject(){
editName.Text = subjekt.getName();editAlter.Value = subjekt.getAlter();editGehalt.Text = String.Format("{0:c}", subjekt.getGehalt());
}
private void readSubject(){
string name = editName.Text;int alter = (int)editAlter.Value;string gehaltText = editGehalt.Text;double gehalt = (double)Decimal.Parse(gehaltText);
subjekt.setName(name);subjekt.setAlter(alter);subjekt.setGehalt(gehalt);
}
62
Folie 123se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Subjekt und Listen-ModellDas 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
Kapitel 9: Unit-Test
ÜbersichtTestprojektTestklasse und Testattribute
63
Folie 125se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Teststufen - ÜbersichtTestgegenstand sind Komponenten, teilintegrierte Systeme oder Systeme
Bilder: Martin Glinz, Universität Zürich
Unit-Test, Komponententest, Modultest„autarke“ Komponenten werden isoliert getestet
IntegrationstestTeilintegrierte Komponenten testen die Komponenteninteraktion
SystemtestTest des Gesamtsystems
Folie 126se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
TeststufenUnit-TestIntegrationstestSystemtest
Weitere TeststufenUser Acceptance Test (UAT)Beta-TestAbnahmetestDeployment-Test
Test gegen nichtfunktionale Anforderungen
64
Folie 127se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Unit-Test (1)„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!)
Folie 128se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Unit-Test (2)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 RealtimeParametrisierte Testfälle können mit Daten aus einer externen Datenquelle befüllt werden
65
Folie 129se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Testaufbau
Prüfling
Testtreiber
StubEin Stub (Platzhalter) ersetzt eine vom Prüfling genutzte Funktion
Der Testtreiber startet die Ausführung des Prüflings und nimmt Resultate entgegen
Folie 130se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Unit-Test mit Visual StudioEs wird ein Test-Projekt angelegt; das Projekt mit den zu testenden Klassen wird „referenziert“ (Hinweis: die zu testenden Klassen müssen dort public sein)Testklassen und Testmethoden werden über Attribute gesteuertEs ist oft hilfreich, wenn die zu testende Klasse eine Equals-Methode 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");
}}
66
Folie 131se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Beispiel: Testmethoden für BruchBeispiel Testmethoden
[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);
}
Ausgangssituation
Aktion
Resultatsvergleich
Ausgangssituation
Aktion
Resultatsvergleich
Folie 132se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Unit-Test Attribute[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]
Aufräumarbeiten, die nach jedem einzelnen Testfall[TestMethod] aufgerufen werden
[TestMethod]
Ein Testfall
67
Folie 133se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Entwurfskriterium: TestbarkeitDie Isolierbarkeit einer Unit ist eine Voraussetzung für Unit-TestsIsolierbare Units entstehen bei Entwurf nicht zwangsläufig – die Isolierbarkeit muss aktiv im Entwurf herbeigeführt werdenEmpfehlung: Testbarkeit sollte bei Entwurfsreviews mit einbezogen werdenZur 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.
Folie 134se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Test-First-AnsatzEs werden zuerst die Testfälle (in der Regel eingebettet in den Testtreiber) implementiert und anschließend der produktive ProgrammcodeTest-First entstammt den agilen Vorgehensweisen (Extreme Programming)Vorteile
QS der AnforderungAutomatisierung spart AufwandDer Test verliert den negativen BeigeschmackTestfälle werden dokumentiert und sind reproduzierbar
In der Praxis stellt eine unvollständige Unit-Spezifikation ein großes Problem dar!
68
se-rt www.se-rt.de - © 2009 Software-Engineering Rat&Tat - TTI GmbH C# 1.01
Einführung in die Programmiersprache C#
Rainer [email protected]