C# für Umsteiger

Transcrição

C# für Umsteiger
AG Spieleprogrammierung
Do, Hoang Viet ([email protected])
2011-01-10
Die Programmiersprache C#
 Aussprache: „C Sharp“ oder „Cis“
 Programmiersprache des .net-Framework
 Anwendungen von .net Framework
Die Programmiersprache C#
Vorteile des .net Framework:
Plattformunabhängig (PC, WinPhone, Xbox, RIA) und
OS-unabhängig
2. Sprachunabhängig: „Mischen“ von mehreren
Programmiersprachen möglich
3. Automatische Speicherverwaltung, aber auch “unsafe”
Code möglich!
1.
Eigentschaften von C#:
 objekt-orientiert, typsicher, case-sensible, Unicode
.net - Grundbegriffe
 Compilation Unit, Source Code, C# Compiler (csc.exe)
 Assemblies
 Common Intermediate Language (CIL, MSIL)
 JIT, Jitter
 Common Language Runtime (CLR)
 Common Type System (CTS)
 Common Language Specification (CLS)
 Memory Management, Garbage Collector (GC)
Namespace
 Die gesamte „.net Framework Class Library“ (FCL) ist
in dem Namensraum „System“ definiert
 Keyword: using <namespace>;
 Entspricht dem using aus C++ nicht dem „import“ von
Java
 Assemblies werden referenciert
 Übersicht vom .net Framework 4: Link
Verbatimstring & -identifier
 Verbatimidentifier: @<bezeichner>
 Schlüsselwörter als Namen
 @ sind nicht Teil des Namens!
 Verbatimstring: @“<beliebige Inhalt>“
 Keine Übersetzung der Escape Characters
 Zeichenumbrüche und Tabs sind Teil des Strings
 ““ (2x) für “
 Beispiel: @“C:\Userfiles“
Lokale Variablen: nullable types
 Nullable types
 <type>? <bezeichner> [= <expr>];
 Als <expr> ist nun „null“ möglich
 Intern: Instanzen der Struktur System.Nullable<T>
 Beispiel:
 int? Kinder_von_Hans = 0;
 int? Kinder_von_Klaus= null;
 Hans hat keine Kinder. Kinderanzahl von Klaus ist
unbestimmt/unbekannt.
 Null coalescing: int a = b ?? -1;
 Variable a wird den Wert von b zugewiesen, wenn b nicht null
ist, ansonsten -1. (b muss nullable type sein)
Typen in C#
Reference
Type
Unsafe
Pointer
Heap
(Managed/Unmanaged)
Value Type
Stack
Klassen
 Essentiell für C#, da keine globale Funktionen, keine
globalen Variablen
 Syntax:
[attributes] [accessibility] [modifiers] class <identifier>
[: <baselist>] { <class_body> }
 attributes sind optional
 Beispiel: Serializable
 Thema „Metadata & Reflection“
Klassen
 accessibility für Klassen: „Zugriffsberechtigung“
 public
Eigenen Assembly und referenzierende Assembly
 internal Nur Eigene Assembly (default)
 modifiers:
 abstract Keine Instanzen möglich
 sealed
 static
 unsafe
Keine Ableitung möglich
nur statische Methoden
unsafe-Konstrukte möglich wie pointer.
(+ unsafe compiler option)
Klassen
 baselist
 Eine Elternklasse!
 Keine Mehrfachvererbung möglich
 Mehrere Interfaces
 class_body
 Definition von „Verhalten“ (engl. behavior) und
„Zuständen“ (engl. states)


Verhalten
Zuständen
= Funktionale Members
= Datenmembers
 Erinnerung: public Schnittstellen und den Rest
verdecken!
Klassenmembers
Datenmembers
• Fields
(„Objekteigentschaften“)
• Constants
(„Klassenkonstanten“)
• Nested Types
(„Eingebette Klassen“)
Funktionale Members
•
•
•
•
•
•
Methoden
Konstruktor/ Destruktor
Properties & Indexers
Delegates
Events
Operatoren
Zugriffsmodifikatoren für Members
Zugriffsmodifikator
Außerhalb
Kinderklassen
public
Ja
Ja
internal
Ja (innerhalb der AS)
Ja (innerhalb der AS)
internal protected
Ja (innerhalb der AS)
Ja
protected
Nein
Ja
private
Nein
Nein
Instance und Static Members
 Aufteilung der Members:
 instance Zugriff/Aufruf über Objekt
 static
Zugriff/Aufruf über Klasse
 Bestimmte Membertypen können nicht static/instance sein

Beispiel: Destruktor (nicht static), Operatoren (nicht instance)
 Zugriffsoperator:
 instance <object>.<member>[(…)];
 static
<class>.<member>[(…)];
 Lifetime („Gültigskeitsdauer“):
 static
nahe zu geknüpft an Anwendung
 instance beschränkt
Static Class
 Klasse nur mit statischen Members
 D.h. Members können nur über die Klasse selbst aufrufen werden
 Keine Instanzierung möglich
 Klassen-Modifier „static“ benutzen
 Syntax: […] static class <identifier> { <class_body> }
this-Objekt
 Das aufrufende Objekt
 Als „readonly“ definiert
 Gewährt Zugriff auf die eigenen Members
 static-Methoden können nicht auf instance-members zugreifen.
 Wird implizit angewendet und ist optional
this.<member> ist das selbe wie <member>
 Verwendungszweck:
 als Rückgabewert, als Parameterwert, für IntelliSence, für bessere
Lesbarkeit.
Datenmembers
 Zugehörige Member-Typen
 Constants
(„Konstanten“)
 Fields
(„Objekteigentschaften“)
 Nested Types („Eingebette Typen“)
 Wegen Abstraktionsprinzip meisten als „private“
Klassenkonstante (Constant)
 Syntax:
[accessibility] [modifier] const <type> <identifier>
= <const_expr>;
 Werden zur Kompilierungszeit erzeugt und bleiben
persistent über die gesamte Laufzeit
 <const_expr> Auswertung zur Kompilierungszeit
 Value-Types (bspl.: double), Strings, oder null für RefTypes
 Einzige modifier ist „new“
 Versteckt Constant desselben Namens von base-type. Zugriff
dann über den Klassenname der base-type.
 Impilizit static (bei Angabe: compiler error)
Beispiel: Konstanten
class BaseType {
const int
c = 100;
const string a = "blah";
}
class DerivedType : BaseType {
new const int c = 200;
}
Fields
 Syntax:




[accessibility] [modifier] <type>
<identifier>[ = <expr>];
Zustandsinformationen, gebunden am Objekt
Im managed Heap gespeichert
Initialisierung ist optional, ansonsten default-wert der
Art 0 oder null
Alle modifier: readonly, static, new and volatile
Fields – modifier „readonly“
 Ähnlich eine Konstante
 Wertsetzung wird im Constructor durchgeführt
(sprich zur Laufzeit)
 Zur Initialisierung: Bezug auf static-members
möglich.
Beispiel: Objekteigenschaften
class Figur {
int
c = 100;
readonly string _name;
public Figur(string name) {
_name = name;
}
}
Nested Types
 Typen, die innerhalb einer Klasse / Struktur erstellt
werden.
 Alle modifier anwendbar
 private Benutzung nur in der „outer-class“
 public
Benutzung auch außerhalb der Klasse
 static members sind verfügbar innerhalb des Nested
Types ungeachtet vom accessibility.
 „this“-Objekt innerhalb der Nested Types bezieht sich
nur auf members des Nested Type
Eingebettete Typen
class CPerson {
string _fname =null, _lname =null;
Address _home, _work;
class Address {
string _street, _city, _postal;
// ...
}
// ...
}
Funktionale Members
 Verkörpern das „Verhalten/Aktionen“ der Klasse
 Zugehörigen Typen
 Methoden: Funktionen mit Eingabe und Rückgabe
 Properties: „Data member“, welches mit getter und
setter definiert wird
 Indexers: spezielle Properties, die auf die this.Reference
angewendet werden (später)
Methoden
 Syntax: [attributes] [accessibility]
[modifiers] <return_type> <identifier>
([parameter_list]) { [statement;]};
 [attributes]
 Obsolete, StrongNameIdentityPermission,
InternalsVisibileTo
 [accessibility]
 private, public, protected, internal, internal protected
Beispiel: Methoden definieren
class MyClass{
// spezielle Funktion
public void method() {
// tue irgendwas
}
}
Methoden: Rückgabewert
 Rückgabe über return <val> oder return; bei void
 Warnung: unerreichbare Anweisungen durch return
 Error: Pfade ohne Rückgabewert
 Kann sowohl als L-value als auch R-value (bei
Referenzen) genutzt werden. (Ausnahme: void)
 Aufrufende Seite: Rückgabe immer eine Kopie (im
Stack), selbst bei Reference-Types.
Methoden: Parameterliste
 Anzahl ist im allgemeinen fest: 0 oder mehr
 Schlüsselwort „param“ für variable Längen (später!)
 Veränderungen an den Parameter werden per-default
nach Abarbeitung verworfen (passed-by-value):
 Lösung:


„ref“ benutzen
„out“, wenn keine Initialisierung zuvor gewünscht
 Achtung: bei den Reference Type sind die Members
dennoch veränderbar! (Aber die Klasse selbst nicht)
Beispiel: ref- / out-modifier
class CExample {
// Änderungen an den members bleiben
public static void Set(CNumber x) {
x.val = 1;
}
}
Methoden überladen
 Funktionsauflösung (engl. Function resolution)
geschieht zur Kompilierungszeit.
 Bei Mehrdeutigkeit, Compilerfehler
 Variable Parameterliste ist gültige Überladung
 Auflösung: zuerst fix-length, dann wenn keines passt
variable-length.
Methoden überladen
 Mehrere Implementierung für Funktionen selben
Namens einer Klasse
 Zweck: Ähnliches Verhalten
 Selbe Name, aber eindeutige Signatur



Anzahl der Parameter, Typen der Parameter (inklusive
parameter-attribute wie „out“ / „ref“. Aber nur eins!)
Rückgabewert gehört nicht dazu!
static oder instances ist nicht Teil der Signatur (außer beim
Konstruktor)
Konstruktoren (engl. Constructors)
 Syntax: [accessibility] [modifer] <typename>
([parameterlist])
 Selbe Name wie Klasse
 instance-constructor: initialisiert den Zustand
 Aufruf durch new Operator
 static-constructor: (später)
 Können nicht explizit gerufen werden.
Konstruktoren
 [accessibility]
 Public & co.: Benutzung im aktuellen Assembly und
referrenzierende Assemblies
 private oder protected: unterbinden die Erstellung
eines Objektes außerhalb der Klasse oder von einem
Erben der Klasse
 [modifer]
 extern (implementierung in einer externen DLL)
 Constructor haben implizit den Rückgabewert void
Konstruktoren
 Klassen haben immer einen Konstruktor
 Wenn keine definiert, dann Default Constructor:
 Weist default values den Fields zu
 Aufruf mit parameterlosen new typename()
 Überladung möglich
 Funktionsauflösung durch ‚new‘ – Operator
 Wenn ein eigene Constructor mit Parameter definiert
wurde, muss Default-Constructor selbst definiert
werden
Konstruktoren
 Konstruktoren können die this-Referenz benutzen um
sich gegenseitig aufzurufen (selbst der Default
Constructor). Aber nicht innerhalb des
Funktionsrumpf!
 „colon syntax“, nur für Konstruktoren verfügbar
Beispiel: colon-syntax
class CBook {
int
_pages;
string _isbn, _author;
CBook() : this(0, "", "") {
}
CBook(int pages) : this(_pages, "", "") {
}
CBook(int pages, string author, string isbn) {
// ...
}
}
Klassenkonstruktor
 Zweck:
 Initialisieren von static fields
 Aufruf:
 Werden nicht explixit aufgerufen! Sondern wenn die
Klasse zum ersten Mal referrenziert wird.
 Einschränkungen
 Keine accessibility
 Keine Parameter
 Können nicht überladen werden
Beispiel: Object initializer
Person p = new Person() {
FName = “Bruce",
LName = “Wayne",
WorkP = new Address() {
City = “Gotham City“
}
};
Destruktoren (engl. Destructor)
 Syntax:
[extern] ~<typename>() {[func_body]};
 Werden nicht explixit gerufen, sondern vom Garbage
Collector zur unbestimmten Zeit
 Werden vor dem Entfernen des Objektes aufgerufen
 Methode mit selben Name wie Klasse mit Prefix ~
(Tilde)
Destruktoren
 Unterschiede zu anderen member functions:
 Kann nicht überladen werden
 Leere Parameterliste
 Keine Zugriffsbestimmung
 Einzige und implizite Rückgabewert ist void
 Einzige modifier ist „extern“
 Werden nicht geerbt (später!)
Properties
 Ein Field, das mit eine get & set – method realisiert wird.
 get als R-value, genutzt innerhalb eines Ausdruckes
 set als L-value
 Beide werden nicht direkt aufgerufen.
 Einige Vorteile gegenüber Field
 Stabiler als public & protected fields, da eine Überprüfung
stattfindet
 lazy initialitaion: initialisieren bei Bedarf
 Write-only & read-only möglich; Fields nur read-only
 Können in interfaces aufgenommen werden; Fields nicht
Properties
 Syntax:
[accessibility] [modifier] <type> <identifier> {
[accessibility] get {[f_body]}
[accessibility] set {[f_body]}
}
 [accessibility] kann von einem der beiden geändert werden
 set:
 Implixit einen Parameter. Schlüsselwort „value“
 get:
 Keine Parameter
 Rückgabewert vom identifier
Beispiel: Properties
class CPerson {
string fname =null, lname =null;
int _age;
public int age {
get { return _age; }
set { _age = value;}
}
public string fullname {
get { return fname + ", "+ lname; }
}
}
Properties
 Properties haben keinen festen Speicherbedarf
 keinen: reine Berechnungen
 1 to 1:
1 Field für ein Property
 1 to many:
Mehrere Properties auf ein Field
 Many to 1:
Mehrere Felder für ein Property
 read-only: nur get-Methode
 write-only: nur set-Methode
Properties
 Error Handling
 Möglichkeit A: Exception werfen (später)
 Möglichkeit B: null setzen (u.a. GC)
 Auto-Impl.-Properties:
accessibility modifier type identifier
{modifier get ; modifier set;}
 Speicher wird implizit erzeugt: anonym
Partial Type
 Definition über mehrer Sourcefiles
 Zusammenfügen bei der Kompilierung
 „Komplette“ Typ Definition mit keyword „partial“ in
der jeweiligen Datei.
 Vorteilhaft bei Teamarbeit: jeder implementiert seinen
Teil!
Partial Type
 Jedes Partial Type enthält das Schlüsselwort „partial“
 Alle Definitionen haben die gleichen accessibility
 Wenn eine Definition
 als „sealed“ definiert ist, dann auch Endklasse
 Als „abstract“ definierit ist, dann Endklasse
 geerbert wird, dann komplette Endklasse
Partial Method
 Darf keinen Wert zurückgeben (Type: void)
 Schlüsselwort „partial“
 Nur eine Deklaration und eine Definition
 Standard accessibility ist private
 Keine „out“-Parameter
 Wenn keine Definition, dann wird Deklaration bei
Kompilierung verworfen.
Structures
 Leicht gewichtete Klassen, die im Stack gespeichert
werden
 Daher: klein halten!
 Syntax:
 [attributes] [accessibility] struct
<identifier> [: interfacelist] { [body]
}
Structures
 Unterschiede zu Klassen:
 Structures sind sealed
 Werden von System.ValueType abgeleitet (statt direkt von
System.Object)
 Fields können nicht inialisiert werden bei der Deklaration der
Struktur, außer const members
 Default Constructor kann nicht ersetzt werden
 Selbst definierte Constructors müssen alle Fields setzen und
ersetzt den Default Constructor nicht!


Aufruf über new – Operator (bleibt aber im Stack)
new Operator ist optional und wird genutzt um selbst-definierte
Constructors zu rufen. Ansonsten implizite Aufruf von DefaultConstructor
 Keinen Destructor
Enumeration (Aufzählung)
 Menge von zusammenhängen und diskreten Werten
 Syntax: [accessibility] [modifier] enum <identifier> [:
basetype] { [memberlist] };
 accessibility: freiwählbar
 basetype: interne Datentyp (default: Integer)
 Ganzezahlige Typen (außer char)
 Werden häufig als Nested Type definiert
Enumeration
 memberlist:
 Auflistung aller Element (1.Element = 0, 1, …, n-1)
 Zuweisung bestimmte Wertes ist jederzeit möglich.
Folgeelemente werden successive nummeriert.



Keine Reihenfolge notwendig
Duplikate möglich
Nicht alle Elemente müssen einen Wert zugewiesen bekommen
 Ernumerations sind instances von System.Enum
 Enum.GetName(…)
Label vom Element
 Enum.GetNames(…)
Alle definieren Labels
 Enum.GetValues(…)
Alle Werte
 Enum.GetUnderlyingType(…)
Beispiel: Enumeration
public enum EWeekDay
Wednesday = 4,
Monday = 2,
Tueday,
//
Thursday = 5,
Friday,
//
Saturday,
//
Sunday
//
}
{
hat Wert 3
hat Wert 6
hat Wert 7
hat Wert 8
Equivalance versus Identity
 Äquivalent (engl. „Equivalence“): Objekt mit gleichen
Werten
 Identisch (engl. „Identity“): Objekt im selben
Speicher
 Zuweisung:
 Bei Value Type:, der Wert nicht etwa der Speicherort
wird übergeben => Äquivalenz
 Bei Reference Type: Der Speicherort wird übergeben
=> Äquivalenz & Identisch
Grundlage
 engl. „Inheritance“
 Zweite Grundsteinen des OOP
 Von Verallgemeinerung bis Spezialisierung
 Beispiel: Lebewesen, Tiere, Säugetiere, Mensch
 base-class („Elternklasse“)
 derived-class („abgeleitete Klasse“)
 Vorteil: Wiederverwendung von Code!
Grundlage
 Vererbung ist eine „ist“ Relation und keine „hat“
Relation zwischen den Klassen
 Beispiel: Klasse Zeitstempel soll von Klasse Stempel
abgeleitet werden, anstatt von Klasse Zeit, da es ein
spezielle Stempel ist und nicht eine spezielle Zeit.
 Zeitstempel ist ein spezielle Stempel
 Zeitstempel enthält Informationen über die Zeit, es ist
aber keine spezielle Form der Zeit!
Grundbegriffe
Inheritable class / erbbare
Klasse
Inheriting class / erbende Klasse
Base
Basisklasse
Derived
Abgeleitete Klasse
Superclass
Superklasse, Übergeordnete Klasse
Subclass
Subklasse, Untergeordnete Klasse
Parent
Elternklasse
Child
Kindklasse
Ascendant
Vorgänger
Descendant
Nachfolger
cross-language inheritance
 Möglich zwischen managed Programmiersprache, da
Vererbung auf Ebene des CIL funktioniert.
 Für Common Language Runtime (CLR). CIL-type erbt CIL-
type. Anstatt C# type erbt VB.net type.
 Vorteil:
 Teameinsatz: Unterschiedliche Programmiersprachen für das
selbe Projekt
 Libraries nutzbar, geschrieben in anderen Sprachen
 Einschränkung:
 Common Language Specification (CLS). z.B.: VB ist caseinsensitiv, während C# case-sensitiv => Mehrdeutigkeit
Vererbung allgemein
 Syntax:
class <dev-class> [: <baseclass> [, <interface1>] …] {
}
 Jeder Klasse hat max. einer Elternklasse
 in C++: Mehrfachvererbung erlaubt.
 in C# & Java: Interfaces
 Elternklasse musst selbe oder höhere accessibility
haben als Kindklasse, sonst compiler fehler!
Members überschreiben
 Überschreibar sind alle funktionale instance-members
(Methoden, Properties, Indexers und Events)
 Data Members und Static Members können nur
versteckt werden.
 Durch das Überschreiben entstehen Probleme
 „fragile base class problem“
 in C# wie in C++: Elternklasse muss es explicit erlauben!
 In Java per default erlaubt
„virtual“ und „override“
 base-class erlaubt mit Schlüsselwort „virtual“
 Gilt nicht nur für die unmittelbare derived-class
 Funktionale Instance-Members: Methoden, Properties,
Indexers und Events
 derived-class überschreibt mit Schlüsselwort „override“
 Zu Properties: man kann nicht read-/write-only verändern!
 Schlüsselwort „base“:
 Zugriff auf unmittelbare base-class (nur public & protected)
 „base.base.member“ ist nicht möglich!
Überschreiben Vs. Überladen
Überladen
Signatur Funktionen haben
unterschiedliche Signatur.
Identifier
Überschreiben
Funktion wird ersetzt und
muss exakt dieselbe Signatur
besitzen! (compilerfehler)
Funktionen haben denselben Bezeichner.
Permissio Keine gesonderte Angaben
n notwendig.
Basisklasse muss es explicit
erlauben.
Erbende Klasse muss es
explicit angeben.
Zusammenfassen: komplette unterschiedliche Ansätze!
Schlüsselwort new
 verdeckt die jeweilige Methode
 in C#: hide-by-signature
 .net: hide-by-signature und hide-by-name (gesamte
Interface)
 Zugriff mit „base“ möglich
 per-default: Definition einer Methode (mit der
selben Signatur) in derivated-class.
Schlüsselwort new
 Unterschied zwischen new & override mit virtual
 Durch new „verschwindet“ virtual in den nächsten
Ebenen, da 2 unterschiedliche Methoden!
 new + virtual gleichzeitig nutzbar
 Data Members und Static Members können nur mit
new verdeckt werden; sind nicht überschreibbar.
Konstruktor & Destruktor
 werden nicht vererbt!
 Alle Konstruktoren der Vererbungskette werden
aufgerufen (bottom-up: Urklasse als Erstes)
 Per default, wird der Standardkonstruktor aufgerufen.
 Für andere Konstruktoren colon-syntax benutzen mit
„base“ statt „this“

Die Benutzung von base(this) ist nicht möglich, da das Objekt
noch nicht erstellt wurde.
 Destruktoren in umgekehrte Reihenfolge
Abstract Klassen
public abstract class CShape {
public void scale();
public void stretch() {
// ...
}
}
Abstrakten Klassen
 engl. abstract classes
 (unvollständige) abstrakte Entität
 class-modifier: abstract
 können keine Objekte erzeugen
 Nur für Vererbung
 static classes können nicht abstract sein.
Abstrakten Klassen
 Funktionale members (Methoden, Properties,
Indexers und Events) können ebenfalls abstract sein.
 nur Deklaration, kein Funktionsrumpf
 implicit virtual
 static members können nicht abstract sein!
Sealed Classes
 „Blätter“ vom Baum „Klassenhierarchie“
 Nicht ableitbar, „Gegenteil von abstract“
 Keine static members
 Value Types sind sealed!
Extension Method
 Erweitern von „geschlossenen“ types wie value types
 static method in static class
 Type:
 Erste Parameter beginnt mit „this“ und dem zu
erweiternden Type
 Aufruf als gehöre Methode zur ursprünglichen Type
 Interface:
 Auch anwendbar für interfaces
 Aufrufbar von allen Types mit dem interface
Extension Method
 Wenn instance-method und extension-method die
selbe Signatur haben, wird instance-method gerufen.
 Wenn 2 extension-method die selbe Signatur haben,
muss man die Methode explicit aufrufen.
 extension-method muss in selbem Scope sein!
Polymorphie
 Ein der Hauptvorteile von Vererbung
 Dritte Säule von OOP
 late binding: die „richtige“ Funktion wird zur
Laufzeit bestimmt.
 Realisiert durch „Casten“ bis gemeinsamer Type
 Gegenteil von early binding (binden zur
Kompilierungszeit)
 Achtung bei der Nutzung von „new“
 Es wird nicht immer die „letzte“ Definition aufgerufen!
Polymorphie - Casten
 Casten in einer Basisklasse ist immer möglich, selbst
abstrakte Klassen (und Interfaces)
 Reference Type: Zeiger auf ein Bereich des Objektes
 Value Types in Reference Type: Boxing, Unboxing


Beispiel: Struct zu Interface
Interface ist Reference Type
 Boxing
 „Umwickelt“ des Value Type
 Wert wird im Heap gelagert (da Reference Type)!
 Original (Value Type) hat nix mit der Kopie zu tun.
System.Object
 Mutter aller Klassen!
 Wird von allen Klassen geerbt direkt (wenn keine
base-class angegeben ist) oder indirekt!
 Redundanz: explicit von System.Object erben
 Members:
 Constructor, Equals, Finalize, GetHashCode, GetType,
MemberwiseClone, ReferenceEquals, ToString
 Außer Constructor sind alle überschreibbar
 Schlüsselwort: object
Object.GetHashCode
 Syntax:
 public virtual int GetHashCode()
 Hash Code soll konsistent bleiben nach der Erstellung
des Objektes um Kollisionen zu vermeiden
 Keine Abhängigkeit von Objektdaten (Fields)
 .net bietet keine Garantie für
 Kollisionsfreie Implementierung
 Konsistenz über verschiedene .net Versionen
Object.Equals
 Definition
 public virtual bool Equals(object obj)
 public static bool Equals(object obj1, object obj2)
 Vergleich auf Identität! („selbe Objekt?“)
 Reference Type: Zeiger auf dasselbe Objekt
 Value Type: Werteabgleich
 Vergleich hat 4 Eigentschaften:
 reflexiv: 𝑂𝑏𝑗 = 𝑂𝑏𝑗
 symmetrisch: 𝑂𝑏𝑗1 = 𝑂𝑏𝑗2 ⇒ 𝑂𝑏𝑗2 = 𝑂𝑏𝑗1
 transitiv: 𝑂𝑏𝑗1 = 𝑂𝑏𝑗2 ∧ 𝑂𝑏𝑗2 = 𝑂𝑏𝑗3 ⇒ 𝑂𝑏𝑗1 = 𝑂𝑏𝑗3
 konsistent: wenn sich der Zustand nicht ändern, bleibt
Gleichheit
Object.Equals
 Operator == und Operator != ruft nicht Equals auf!
 Alle 3 Methoden sollten überschrieben werden
 2 identische Objekte sollen den selben HashCode
besitzen, daher Compiler Warnung, wenn
GetHashCode() nicht überschreiben wird
Object.Equals
public static bool operator==(Book b1, Book b2) {
return obj1.Equals(obj2);
}
public static bool operator!=(Book b1, Book b2) {
return !obj1.Equals(obj2);
}
public override bool Equals(object o) {
// Code ...
}
Object.ReferenceEquals
 Syntax:
 public static bool ReferenceEquals(object o1, object o2)
 Vergleich Identität (dasselbe Objekt!)
 Verwendungszweck:
 Wenn Equal überschrieben wird.
Object.GetHashCode, Object.Equals
und Object.ReferenceEquals
 GetHashCode, Equals und ReferenceEquals sind
voneinander unabhängig!
 GetHashCode soll kollisionsfreie Hash-Werte
zurückgeben.
 Die static Variante von Equals ruft die instance
Variante von Equals auf
 ReferenceEquals kann nicht überschrieben werden
und vergleicht die Reference.
Object.GetType
 Syntax
 public Type GetType()
 Themengebiet: „Reflection“
 Liefert Type-Object
 GetMethods ( )
 GetFields ( )
 usw.
 Nicht überschreibar, da nicht als „virtual“ definiert
Object.ToString
 Repräsentation des Objektes als string
 reference type:

per default „vollständige Name“ (mit Namespace)
 value type: Wert
 Beispiel:
int a = 10;
Console.WriteLine(a.ToString());
Object b = new Object();
Console.WriteLine(b.ToString());
// 10
// System.Object
Object.MemberwiseClone
 Syntax:
 protected object MemberwiseClone()
 Eine Schattenkopie wird erstellt
 Value Type: Wert wird dupliziert („Echte Kopie“)
 Reference Type: Zielobjekt wird bitweise kopiert!
(Achtung bei Type mit Reference type als Members)
 Lösung: Interface „ICloneable“, Methode „Clone“
Interfaces
 Problem: Eine Klasse kann nur eine base class haben,
aber mehrere Interfaces.
 Im Gegensatz zu C++ mit Mehrfachvererbung
 Syntax: [attributes] [accessibility]
[modifiers] interface <identifier> [:
baselist] { [body] }
 Interface:
 Ansammlung an Deklarationen von funktionalen
Members
 Interfaces können keine „Objekte“ (instances) erzeugen!
Interfaces
 Ableitende Klasse implementiert alle deklarierten
funktionalen Members
 Interface bleibt unverändert, sonst €€€!
 Ein Interface beschreibt eine Eigenschaft/Fähigkeit
eines Objektes, daher den Suffix „-able“ und Präfix „I“:
Comparable, IEnumerable, …
 Members sind implizit public und abstrakt
 Keine Änderung möglich. (Angabe => Compiler-error)
 Implementierende Klasse muss „public“ angeben!
Vererben von Interfaces
 Erweitern der Deklarationen an funktionalen
Members von erbendendem Interface
 Bei „Namensüberlappung“ (durch Vererbung) gibt es
Compiler Warnung:
 „new“ benutzen!
 Bei „Namensüberlappung“ (durch base-list):
 Eine Implementierung für alle Deklarationen
Explicit Interface Member
Implementation
 Member - Definition an einem speziellen Interface
binden/zuordnen
 Zugriff:
 Aufruf nur durch das Interface möglich!
 In das jeweilige Interface casten!
 Implementierung:
 Keine Angabe der accessibility
 Identifier: <Interface>.<method>
Überschreiben von
Implementierungen
 Die implementierende Klasse kann Definition kann
als virtual markiert sein!
 Erbende Klassen können mit override Implementierung
überschreiben
 Explizite Implementierung können nicht
überschrieben werden.
Interface Vs. Abstrakte Klassen
Interfaces
Abstrakte
Klassen
Deklaration und Definition
von funktionale Members.
Nur Deklaration
Sowohl
Deklaration als
auch Definition
Vererbung
Nur Interfaces
Interfaces und
andere Klassen
Kon-/Destruktoren
keine
Beide
Erbbar von Strukturen
ja
nein
Grundlagen
 Deutsch: Ausnahmebehandlung, Fehlerbehandlung
 Ausnahmezustände, die den normalen Programmfluß
verändern.
 System Exceptions (Systemfehler):
 Werden von CLR ausgelöst
 Beispiele: out-of-Memory, divide-by-zero, null-
reference, stack-overflow
 Application Exceptions (Anwendungsfehler)
 Werden von der eigenen Anwendung ausgelöst.
Grundlagen
 Teuer im Vergleich mit anderen Konstrukten
 In Übermaßen, unübersichtlich und erschweren die
Wartung
 Ständig auftretende „Fehler“ sollten mit Fehlercode
(error codes) behandelt werden.
 Anwendung: Konstruktoren, Properties
 Kurz: nur für Ausnahmefällen gedacht!
Exception Handling in .net
 Läuft auf der CLR Ebene, sprachunabhängig
 Exception von anderen (managend) Sprachen können
abgefangen werden!
 Strukturierte Ausnahmebehandlung mit try & catch
 Aus C++ & Java
 Unstrukturiert (Visual Basic) ist veraltet?!

On error, on resume
Try and Catch
try { [<protected code>] } catch(<filter_1>)
{[code1]} …catch[(<filterN>)] {[codeN]}
finally {[code]}
 0 – N catch-Blöcke, filter ist optional, wenn nur 1 catch
erwünscht ist
try {[code]} catch {[code]}
 0 – 1 finally-Block, aber mindesten eins von beiden (catch
oder finally)
 Achtung: Try niemals um die gesamte Application, nur
den kleinen fehleranfällige Teil!
 Try & Catch lässt sich verschachteln!
Catch - Statement
 Wenn ein Exception auftritt:
1. Die Ausführung im Try-Block wird an der Stelle
beendet!
2. Scope wird verlassen: Daten im Try Block verworfen
3. Von oben nach unten, wird nach dem passenden catch
Block gesucht. Empfohlen: zuerst die spezielle, am
Ende allgemeineren.
 Wenn kein passende catch vorhanden: Unhandled
Exceptions
 Alle Exception erben von System.Exception
 catch(System.Exception) { } entsprich catch { }
Exception weiterleiten
 Exception auffangen und weiterwerfen:
 mit throw except_o oder throw;
 Anwendungsszenarien
 Zentrale Fehlerbehandlungsmodul
 Ressourcen für die Fehlerbehandlung ist nicht verfügbar
 Wenn nur ein Teil der geworfenen Fehler behandelt
werden soll


Ein „all-Exception“ catch für die Fehlerbehandlung
Alle ungewollten vorher catchen und weiterwerfen.
 Exception catchen, Informationen extrahieren und
weitergeben zur Behandlung.
Exception weiterleiten
 Die Weiterleitung kann bis zum End User erfolgen
 Auf der End-User Ebene, sensible oder irrelevante Daten
herausfiltern.
 Üblich: user-relevante Informationen, Hilfe um Problem
zu lösen, Support Link u. ä.
 Alternative: Logs
 Property: „System.InnerException” für
Kettenreaktionen. 2. Parameter vom Konstruktor.
Finally - Statement
 Nach dem catch ausgeführt
 Werden auf jeden Fall ausgeführt, selbst wenn kein
Error aufgetreten ist.
 Verwendungszweck:
 Aufräumarbeiten: Datenbankverbindung auflösen, usw.
 Die Variablen müssen außerhalb von Try definiert
werden, damit man Zugriff im finally-Block hat.
Exception Information Table
 Keine Verzögerung durch die Tabelle, wenn keine
Exception auftreten [MSDN, 07.09.2010]
 Für jeder .net Anwendung, wird eine Tabelle erstellt
 Für jeder Methode wird ein Eintrag erstellt, wenn auch
leer (d.h. keine Exception)
 Weitere Informationen:
http://msdn.microsoft.com/en-us/library/6kzk0czb.aspx
Benutzerdefinierte Exception
 Exception sollen von der Klasse System.Exception
erben.
 System.ApplicationException war angedacht
 Semantikkonflikte vermeiden:
 2 Exception für ein Fehler
 Konvention: „Exception“ als Suffix