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