.Net Framework und C# SS Teil I

Größe: px
Ab Seite anzeigen:

Download ".Net Framework und C# SS 2011. Teil I"

Transkript

1 .Net Framework und C# SS 2011 Teil I Dr. Ute Blechschmidt-Trapp Darmstadt, Darmstadt, 4. April 2011

2 Inhaltsverzeichnis 1 Organisation Praktikum Leistungsnachweis Einleitung Motivation Literatur Ziele der Veranstaltung Net Framework Assembly Anwendungsdomäne (AppDomain) Basisklassen Visual Studio Allgemeine Hinweise Debugger Refactor UML-Diagramme Coding Guidelines Code-Analyse XML-Dokumentationskommentare Unit-Tests P1 - VS 2010: Einrichten und freies Erkunden der Arbeitsumgebung C# kompakt Syntax is vs as Operatoren Partial Typen CTS Strukturen Strings Generika Listen Enumerationen Attribute und Reektion Attribute Reektion Zugri auf Attribute mit Reektion Performance IList, IEnumerable und andere Interfaces IComparable und IComparer IDisposable Sprachbesonderheiten Log/Trace Ausnahmen Indexer Serialisierung P2 - C# kompakt Delegates Generische Delegates Mulitcastdelegaten Ereignisse

3 Inhaltsverzeichnis Asynchrone Delegates LINQ Erweiterungsmethoden Abfragen P3* - Delegates und Events Links Oce-Entwicklung Oce-Dokumente von auÿerhalb verändern oder erstellen Excel-Addin Datenbankanbindung NET Framework-Datenanbieter DataSet DataSet oder DataReader P4* - Datenbanken und Addins Windows Presentation Foundation XAML Architektur von Windows Presentation Foundation und das Programmiermodell Steuerelemente und Layout Container Logischer Baum Visueller Baum Routed Events Command Praktikum P5* - WPF Oberäche Datenbindung DependencyProperty INotifyPropertyChanged Binding DataContext MVVM Praktikum P6* - WPF Datenbindung, Audio-Player Links c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

4 1 Organisation Die Veranstaltung wird mit 2+2 SWS angeboten und ist mit 5 CPs bewertet. Ich setzte Kenntnisse der objektorientierte Programmierung, Datenbank- und Web-Entwicklung voraus. 1.1 Praktikum Das Praktikum ist in zwei Hauptblöcke geteilt. Im ersten Block bearbeiten Sie Aufgaben des Skripts, entwickeln dabei einen einfachen Audio-Player und geben diese ab. Im zweiten Block erstellen Sie eine von Ihnen gewählte und ein konkretes Problem lösende (also nützliche).net-applikation. Auÿerdem arbeiten Sie sich selbständig in ein in der Vorlesung nicht behandeltes.net-thema ein (Zusatzthema). Sie können das Zusatzthema gerne mit Ihrem Projekt kombinieren. Termine mit Anwesenheitspicht sind mit einem * markiert P1* - VS 2010: Einrichten und freies Erkunden der Arbeitsumgebung, Anforderungsanalyse Audio-Player, Aufgaben siehe Abschnitt 2.6 auf Seite 14, Abgabe per Mail bis zum P2 - C# kompakt: Programmieraufgaben und Entwurf Audio-Player, Aufgaben siehe Seite Abschnitt 3.6 auf Seite 44, Abgabe: P3* - Delegates: Aufgaben siehe Abschnitt 3.8 auf Seite 58, Abgabe: P4* - Excel-Addin, Datenbankanbindung: Aufgaben siehe Abschnitt 5.4 auf Seite 66, Abgabe: P5* - WPF-Oberäche: Aufgaben siehe Abschnitt 6.4 auf Seite 76, Abgabe: P6* - WPF Datenbindung und MVVM: Aufgaben siehe Abschnitt 6.7 auf Seite 84, Abgabe: P7 - Ihr Projekt: Projektbeschreibung, Entwurf (Abgabe: ) P8* - Ihr Projekt: Implementation der Grundfunktionalität (Abgabe: ) P9 - Zusatzthema: Zusammenfassung geeigneter Quellen und Implementation einer Demo- Applikation (Abgabe: ) P10* - Zusatzthema: Blogartikel, Finalisierung Projekt und Zusatzthema: Abgabe P11 - Präsentation der Projekte, Abgabe der Projektmappe bis zum Projekt. Im Projekt sollen Sie eine für sich nützliche Anwendung mit momentan empfohlenen Methoden in C# implementieren. Inhalt und Umfang stimmen Sie in P6 mit mir ab. Sie präsentieren/demonstrieren Ihr Projekt den anderen Teilnehmern der Veranstaltung. Zusatzthema. Sie arbeiten sich selbständig in ein in der Vorlesung nicht behandeltes Thema (z.b. XNA, Crystal Reports, MEF, EF, Silverlight) ein. Sie erstellen eine Demo-Applikation und schreiben einen Blogartikel, der für Sie nützliche Quellen und Codefragmente enthält. Diesen Blogeintrag werde ich ggf. überarbeiten und er kann anonym oder in Ihrem Namen auf meinem Blog (bletra.wordpress.com) veröentlicht werden. Abgabe. Während des Semesters nehme ich zu den in obiger Liste gekennzeichneten Terminen Teile des Praktikums ab. Die Deadline geht jeweils bis 23:59 Uhr des angegebenen Datums. Sie können die Aufgaben in Zweiergruppen bearbeiten. Programmcode geben Sie bitte als Zip und Essay-Aufgaben als PDF ab. Zur kontinuierlichen Verbesserung der Veranstaltung können Sie mir mit einem kurzen Feedback helfen: Wie lange haben Sie zur Bearbeitung benötigt? Wo hatten Sie ein Aha-Erlebnis? Welche Aufgaben waren eher langweilig? Zusätzlich geben Sie zu Semesterende alle von Ihnen bearbeitete Aufgaben (inklusive Projekt und Zusatzthema) in Form einer Praktikumsmappe ab. 4

5 1.2 Leistungsnachweis 1.2 Leistungsnachweis Der Leistungsnachweis erfolgt durch eine Klausur am Semesterende. Der Termin und der Raum werden im Prüfungsterminplan festgelegt. Der Inhalt richtet sich nach der Vorlesung im SS Die Klausur wird aus Programmieraufgaben die sich an den Aufgaben im ersten Teil des Praktikums orientieren und aus Verständnisfragen die sich auf in der Vorlesung behandelte, aber im Praktikum nicht notwendigerweise vertiefte Themen beziehen zusammensetzen. Das Praktikum besteht aus zwölf Teilaufgaben. Zu jeder Teilaufgabe ist eine Lösung per Mail einzureichen. Im Praktikum werde ich stichprobenartig Fragen zu den abgegebenen Lösungen stellen. Jede Lösung wird von mir insgesamt mit einem ok bzw. nicht ok bewertet. Für das Testat des Praktikums müssen Sie folgende Bedingungen erfüllen zu allen mit * gekennzeichneten Terminen pünktlich erscheinen, für P1-P6 wenigstens für drei Praktika ein ok erhalten, das Projekt und Zusatzthema (mit Blogbeitrag) bearbeiten und präsentieren und eine Praktikumsmappe abgeben. Zusätzlich können Sie Bonuspunkte für die Klausur am Semesterende SS2011 erwerben: 12 ok: 6 Bonuspunkte 11 ok: 5 Bonuspunkte 10 ok: 4 Bonuspunkte 9 ok: 3 Bonuspunkte 7 ok: 2 Bonuspunkte 5 ok: 1 Bonuspunkt Eine Übertragung der Bonuspunkte ins nächste Jahr wird nicht gewährleistet. 5 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

6 2 Einleitung 2.1 Motivation Warum biete ich dieses Wahlfach an? Ich habe 10 Jahre bei einem zertizierten Partner von Microsoft gearbeitet und dabei Microsofts Entwicklungsumgebung und die Möglichkeiten des.net-frameworks kennen gelernt. Die verschiedenen aktuellen Technologien von Microsoft sind mächtig und es macht Spaÿ, mit einer komfortablen IDE zu arbeiten. Leider oder zum Glück gibt es im.net Umfeld ca. alle 2 Jahre eine neue Version. Glück für die Entwicklerinnen, die stumpfsinniges Arbeiten durch mächtige Werkzeuge und Bibliotheken weiter abgenommen bekommen und leider, da sich die Prinzipien dadurch auch grundlegend ändern können. Was ist also das bleibende Wissen, das in einer Hochschulveranstaltung vermittelt werden soll? Für Entwicklerinnen, die bereits eine OO-Sprache beherrschen, kann dies nicht nur das Erlernen der Sprache C# sein. Das Erlernen einer weiteren OO-Sprache ist keine Herausforderung. C# und Java sind sehr ähnlich. In dieser Veranstaltung werden wir uns also auf die Unterschiede konzentrieren. Der Fokus dieser Vorlesung liegt auf... dem Arbeiten mit VS2010, die Verwendung ausgewählter Klassen des.net Frameworks den sprachlichen Besonderheiten von C# wo nde ich gute Informationen zu momentan empfohlenen Vorgehensweisen und wesentlichen Technologien? Reektion der Möglichkeiten und Grenzen des Frameworks Methoden zur Analyse von generierten Code und des Frameworks an sich Ihren Fragen Das Skript enthält die Praktikumsaufgaben und Fragen. Ein Teil der Fragen dient dazu, Recherchen und Diskussionen anzuregen. Diese Fragen können nicht notwendigerweise eindeutig beantwortet werden. Ein anderer Teil der Fragen eignet sich zur Selbstkontrolle oder auch zur Klausurvorbereitung. Dies ist eine Beta-Version des Skripts. Informieren Sie mich bitte über Fehler, Unklarheiten, Lücken, machen Sie Vorschläge für eine bessere Struktur, verständlichere Formulierungen, Übungsaufgaben, Schaubilder. Ich freue mich über jede konstruktive Kritik. Teil 2 des Skripts werde ich Ihnen zeitnah zur Verfügung stellen. 2.2 Literatur Es gibt viele dicke Bücher zu C#, Asp.Net und anderen Themen dieser Vorlesung. Es gibt meiner Meinung nach wenige gute Bücher, die für Quereinsteiger von anderen OO-Sprachen geschrieben werden, so dass Sie viel Geld für Gedrucktes, dass Sie aus anderen Veranstaltungen kennen, ausgeben. Dies, die Schnelllebigkeit von Microsoft-Technologien und die guten Online-Materialien führen zu folgender Linkliste: Microsoft MSDN Das Microsoft Developer Network Channel9 Videos und anderes Lernmaterial patterns & practices: Microsoft Application Architecture Guide, 2nd Edition library/dd aspx Magazin 6

7 2.3 Ziele der Veranstaltung Visual Studio 2010 and.net Framework 4 Training Kit details.aspx?familyid=752cb b-4732-a383-ed5740f02e93&displaylang=en.net Quellcode: Developer Blogs Code Codeproject Codeplex Design Patterns Code-Snippets: Ziele der Veranstaltung Aus dem Modulhandbuch: Die Studierenden lernen, prinzipielle Probleme und Aufgaben in verschiedenen Anwendungsgebieten nach momentan empfohlenen Methoden mit C# zu lösen. Lehrinhalte: Arbeiten mit der IDE Visual Studio Datenbankanbindung Webentwicklung Desktopentwicklung Komponentenentwicklung Wie eingangs erwähnt, werden nicht alle momentan diskutierten.net-hypes aufgegrien, sondern es geht um best-practice und die zugrundeliegenden Prinzipien. 2.4.Net Framework Lernziele: Grundlegende Arbeitsweise von.net kennen lernen. Die Laufzeitumgebungen von.net und Java vergleichen..net Vokabular lernen. Das.Net-Framework und die zugehörige Laufzeitumgebung basieren auf dem Standard (ECMA-335). Diese Internationale Norm deniert die Common Language Infrastructure (CLI), in denen Anwendungen in mehreren Hochsprachen geschrieben und in unterschiedlichen Systemen ausgeführt werden können. Diese Norm regelt folgende Bereiche: Partition I: Konzepte und Architektur Beschreibt die Gesamtarchitektur der CLI. Speziziert dazu das Common Type System (CTS), das Virtual Execution System (VES) und die Common Language Specication (CLS). Partition II: Metadatendenition und Semantik Enthält Informationen über Metadaten: Das physische Layout der Dateien, die logischen Inhalte und deren Struktur. Partition III: CIL Beschreibt die Instruktionen der Common Intermediate Language (CIL). Partition IV: Bibliotheken Enthält eine Spezikation von Klassen und Klassenbibliotheken, die als Teil der CLI standardisiert sind. Partition V: Beschreibt das einheitliche Debuggingformat. 7 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

8 2.4.Net Framework Partition VI: Anhänge. Abbildung 2.1 zeigt den Weg von C#-Programmcode zum ablauähigen Maschinencode. Abbildung 2.1: Vom C#-Quellcode zur Ausführung des Maschinencodes, Quelle: Microsoft Mit einem Vorcompiler wird Programmcode in die Common Intermediate Language (CIL) (teilweise auch nur Intermediate Language (IL) genannt) übersetzt. CIL ist eine objektorientierte Assemblersprache, d.h. sie kennt komplexe Datentypen und Objekte und Konzepte wie Vererbung und Polymorphie. Das physikalische Ergebnis dieses Compilevorgangs sind die sogenannten Assemblies (siehe Abschnitt auf Seite 8). Die Assemblies benden sich im lokalen Verzeichnis oder sind im Global Assembly Cache (GAC) registriert. Der Just in time compiler (JIT) erzeugt daraus sogenannten Managed Code, der in der Common Language Runtime (CLR) für das jeweilige Betriebssystem umgesetzt wird. Managed Code ist per Denition Code, der von der CLR interpretiert wird. Jeder andere Code ist unmanaged. Unmanaged Code unterliegt also nicht der Aufsicht der CLR, ist plattformabhängig und typischerweise ohne das.net Framework erstellt. Der durch den JIT-Compiler erstellte Maschinencode wird bei Beendigung des Prozesses, der die ausführbare Datei ausführt, verworfen. Daher muss die Methode beim erneuten Ausführen der Anwendung wieder neu kompiliert werden. NGen erlaubt die Vorkompilierung von CIL-Anwendungen in Maschinencode vor der Ausführungszeit typischerweise während der Installation. Frage 2.1 Entspricht die Verwendung von NGen einer herkömmlichen statischen Back-End-Kompilierung? Frage 2.2 Wodurch unterscheidet sich die IL von einer reinen Assemblersprache? 8 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

9 2.4.Net Framework Abbildung 2.2:.Net Framework, Quelle: Microsoft, TrainingKit Merke 1 (Laufzeitumgebung) Der Zwischencode kann mit einem entsprechenden Vorcompiler auf Basis einer beliebigen Programmiersprache erzeugt werden. Ein einheitliches Typsystem (CTS) (siehe Abschnitt auf Seite 20) gewährleistet die gleichberechtigte Kommunikation zwischen verschiedenen Entwicklungssprachen. Abbildung 2.2 zeigt wesentliche Klassenbibliotheken von.net und die Hauptkomponenten der CLR Assembly Ein Assembly ist... eine Menge von Typen, die zusammenkompiliert werden, inklusive Ressourcen wie Bilder. eine Laufzeiteinheit, die als Datei gespeichert wird (*.exe oder *.dll), auch portable Executable (PE) genannt. die kleinste Einheit in Bezug auf Deployment, dynamischem Laden, Sicherheit Versionierung enthält Code (objekorientierter Assemblercode) enthält Metadaten enthält ein Manifest (Inhaltsverzeichnis) ist vergleichbar mit einer Java JAR-Datei ist eine.net Komponente Man unterscheidet zwischen privaten und öentlichen Assemblies. Öentliche Assemblies werden im GAC registriert, was zur Folge hat, dass sie über einen strong name verfügen müssen. Ein solcher Name ist eindeutig, ähnlich einer GUID. Assemblies im GAC stehen allen Applikationen zur Verfügung. Private Assemblies benden sich im Verzeichnis der Applikation, können nur von dieser Applikation verwendet werden und können nicht signiert werden. Der GAC ist ein sicherer Speicher, der verschiedene Versionen einer Assembly enthalten kann. Ein Strong Name setzt sich aus vier Teilen zusammen: 9 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

10 2.4.Net Framework Dateiname, z.b. db.dll Versionsnummer, z.b der Kultur (de-de, en-us,...), Sprach und länderspezische Information einem öentlichen Schlüssel Die Metadaten enthalten den public key, Informationen über exportierte Typen (Name, Sichtbarkeit, Basisklasse, implementierte Interfaces, Members, Attribute), Abhängigkeiten zu anderen Assemblies und Sicherheitseinstellungen. Frage 2.3 Verschaen Sie sich einen Überblick über die global installierten Assemblies auf Ihrer Maschine: (a) Navigieren Sie im Windows-Explorer in das Verzeichnis W indwos assembly. (b) Schauen Sie sich das gleiche Verzeichnis auf der Kommandozeile an. Merke 2 (Assembly) Eine Assembly ist die kleinste Einheit in Bezug auf Deployment, dynamisches Laden, Sicherheit und Versionierung Anwendungsdomäne (AppDomain) Anwendungsdomänen sind isolierte Bereiche im CLR-Prozess. Sie werden auch als leichtgewichtige Unterprozesse oder Pseudoprozesse bezeichnet. Wichtig ist, sie sind KEINE Prozesse! Innerhalb der CLR gibt es keine Hardware-Kapselung. Anwendungsdomänen... Schirmen Applikationen gegeneinander ab Umfassen (und isolieren) Assemblies, Module und Typen einer Applikation, Methodentabellen der geladenen Typen und Statische Felder und Objekte der geladenen Typen Können entweder direkt im Code (System.AppDomain.CreateDomain) oder vom jeweiligen Host der CLR erzeugt werden. Es gibt keine direkte Kommunikation zwischen Anwendungsdomänen. Es ist auch kein direkter Zugri auf Assemblies anderer Anwendungsdomänen möglich. Die CLR verhindert die Übergabe von Objekt- Referenzen zwischen Anwendungsdomänen. Eine Interaktion ist nur über einen speziell gesicherten Inter- Domain-Kommunikationsmechanismus möglich. Typischerweise arbeitet man nur mit einer Anwendungsdomäne. Mehrere Anwendungsdomänen sind erforderlich, wenn Code mit anderen Sicherheits-Einstellungen/Zugrisrechten geladen wird, die Isolation zwischen Code-Teilen explizit gewünscht wird, oder Code unabhängig voneinander terminieren können soll. Für Plug-Ins beispielsweise bieten sich separate Anwendungsdomänen an, also eine AppDomain pro Plug-In. Das Stichwort zur Kommunikation zwischen verschiedenen Anwendungsdomänen ist Remoting. Frage 2.4 Wodurch unterscheidet sich ein Thread von einem Prozess und ein Prozess von einer AppDomain? 10 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

11 2.5 Visual Studio Basisklassen Ein Namensraum ist ein logisches Benennungsschema zum Gruppieren von verwandten Typen. In einer Datei können mehrere Klassen und mehrere Namensräume deniert werden dies erhöht sicher nicht die Übersicht. Namensräume und Klassen sind vom Verzeichnisbaum unabhängig! Mit dem Schlüsselwort using können in C# Namensräume in andere Namensräume importiert werden. Es ist auch möglich, Aliase zu vergeben. Namensräume sind hierarchisch organisiert. Mit using System werden alle öentlichen Typen von System importiert.möchte man eine Klasse innerhalb von System verwenden, so ist diese in Bezug auf System voll anzugeben. Die Basisklassen von.net sind in solchen Namensräumen abgelegt. Die Poster.Net Framework 4 and Extensions oder.net Framework 4 Universe veranschaulichen die aktuelle Struktur und Neuerungen. Frage 2.5 Beschreiben Sie in eigenen Worten die folgenden Begrie und nennen Sie, wo möglich vergleichbare Elemente in Java: Assembly CLR Namespace Anwendungsdomäne Strong Name GAC 2.5 Visual Studio 2010 Visual Studio 2010 ist eine kommerzielle Entwicklungsumgebung für.net-anwendungen. Über MSDNA können Studierende auch die Ultimate-Version kostenlos beziehen und gemäÿ den Lizenzbestimmungen nutzen. Diese Veranstaltung basiert auf VS2010 Ultimate. Die Express-Version ist eine abgespeckte freie Version. An dieser Stelle möchte ich einige hilfreiche Vorgehensweisen und Shortcuts einführen. Erkunden Sie die Entwicklungsumgebung und machen Sie sich mit ihr vertraut. 11 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

12 2.5 Visual Studio 2010 Abbildung 2.3: Refactoring, links VS2010, rechts mit Resharpener Allgemeine Hinweise Applikationen werden in Projektmappen verwaltet. Ein Projekt ist eine logische Einheit und erzeugt eine eigene Assembly. Dies kann eine Consolen-Applikation oder auch ein Datenbankmodul sein. VS2010 bietet IntelliSense, Debuggen, Refactoring und vieles mehr. Sie können mehrere Projekte in einer Solution verwalten. Mit Rechtsklick auf ein Projekt können Sie dieses als Startprojekt festlegen. Wie bei jeder IDE, gibt es auch in VS2010 eine Fülle an Shortcuts. Ein zweiseitiger Überblick bietet Microsoft auf der Seite Visual Studio 2010 Keybinding Posters. ich benutze häug folgende Shortcuts: F12: Zur Denition einer Methode oder Klasse gelangen Sie, in dem Sie den Klassennamen z.b. bei der Instanziierung markieren und nun F12 drücken. Mit Ctrl+Shift+8 kommen Sie zurück in die Codezeile, von der Sie F12 gedrückt haben. Beim Debuggen: F11 (nächste Anweisung), Shift+F11 (aktuelle Methode beenden), F10 (Methode ausführen, nicht Schritt für Schritt). Ctrl+w j: Der Objektkatalog bietet eine gute Übersicht über alle eigenen und referenzierten Objekte mit Methoden, Eigenschaften und Schnittstellen. Mit Ansicht Objektkatalog (Object Browser) geht es auch Debugger In dem Sie links in den grauen Bereich neben eine Codezeile klicken, können Sie Haltepunkte setzen. Der grüne Pfeil startet den Debugger. Wenn Sie nun langsam mit der Maus über eine Variable gehen, sehen Sie den aktuellen Wert. Sie können auch eine Variable markieren, rechte Maustaste und Add watch wählen. Im Fenster Watch sehen Sie die Werte überwachter Variablen. Sie können die Spalte Value auch während der Ausführung editieren. Sie können beim Debuggen auch an jeder Stelle den gelben Pfeil anklicken und nach oben ziehen und so einen kniigen Teil erneut debuggen. Sie können sich mit dem Debugger auch an eine bereits ausgeführte Applikation anhängen. Dies benötigt man häug, um eigene Bibliotheken in anderen Applikationen zu debuggen, z.b. ein Add-In in Excel. Wählen Sie hierfür Debuggen An den Prozess anhängen (attach to process) Refactor VS 2010 bietet bereits einige hilfreiche Refactor-Werkzeuge, wie Umbenennen von Variablen, erzeugen von Properties. Markieren Sie hierzu eine Variable, drücken Sie die rechte Maustaste und wählen Sie nun Refactor. Sie bekommen nun verschiedene Möglichkeiten des Refactorings angezeigt. Wer ein ausgefeilteres Refactoring wünscht, muss das Werkzeug Resharpener installieren siehe Abbildung c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

13 2.5 Visual Studio UML-Diagramme VS2010 ermöglicht die Erstellung verschiedener UML-Diagramme, wie Anwendungsfälle, Sequenz-, Aktivitäts-, Komponenten- und Klassendiagramm. Diese Diagramme nden Sie im Bereich Architektur. Die Diagramme gehören zu einem eigenen Projekttyp, dem Modelierungsprojekt. Per Rechtsklick können Sie aus dem Klassendiagramm den zugehörigen C#-Code generieren. Frage 2.6 Bieten die VS-Diagramme die sonst üblichen Darstellungs-Möglichkeiten von UML? Was fehlt? Coding Guidelines Nach dem Naming Guideline von Microsoft sollen Parameter, Klassen etc. wie folgt benannt werden, Basis ist PascalCase und camelcase: Nur Parameter und private Members sind camelcase Namespace:CompanyName.TechnologyName[.Feature][.Design], Beispiel: Microsoft.Media.Design Klassen: Nomen, Beispiel: class FileStream Methoden: Verben, Beispiel: RemoveAll() Interfaces: Nomen oder Nomenausdrücke, Beispiel: IServiceProvider, IFormatable Diese Namensrichtlinien können Sie mit StyleCop validieren. Auf Assembly-Ebene analysiert das Werkzeug FxCop vorwiegend Designkonventionen für Entwicklerinnen von Klassenbibliotheken (Design Guidelines for Class Library Developers), aber auch einige Namenskonventionen. Weitere Coding Guidelines nden Sie unter: Coding style guideline used by the Microsoft All-In-One Code Framework project team. Coding Guidelines Projekt bei codeplex Sie können natürlich auch einer anderen Richtlinie wie Zend für PHP folgen. Machen Sie dies in der Dokumentation Ihres Codes deutlich Code-Analyse Zur Einhaltung von Coding-Guidelines und anderen Richtlinien können Sie bei den Projekteingenschaften unter der Rubrik Build die Option Enable Code Analysis on Build aktivieren. Eine Übersicht der dadurch überprüften Code-Eigenschaften und zugehörigen Warnings liefert Code Analysis for Managed Code Warnings XML-Dokumentationskommentare In Visual C# lässt sich eine Dokumentation des Codes erstellen. Dazu werden XML-Tags in spezielle Kommentarfelder des Quellcodes unmittelbar vor dem Codeblock eingefügt, auf den sie sich beziehen. Wenn Sie mit /doc kompilieren, sucht der Compiler alle XML-Tags im Quellcode und erstellt eine XML-Dokumentationsdatei. XML-Dokumentkommentare sind keine Metadaten und sind nicht in der kompilierten Assembly enthalten. Folglich ist der Zugri auf sie über Reektion nicht möglich. Wenn Sie in der IDE /// vor einem Codeblock eingeben, erzeugt Ihnen VS automatisch einen passenden Kommentar. Möchten Sie zusammenhängende Methoden, z.b. ctor (Konstruktoren), private Methoden o.ä. einfach ein- und ausklappen können, so verwenden Sie #region ctor... #endregion. Mit Hilfe von Werkzeugen, wie z.b. Sandcastle - Documentation Compiler for Managed Class Libraries oder Doxygen können Sie aus der XML-Datei eine lesbare Dokumentation erzeugen. 13 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

14 2.5 Visual Studio Unit-Tests VS2010 bietet eine sehr einfache Möglichkeit, Unit-Test innerhalb von.net zu erstellen. Microsoft bietet ein eigenes Test-Framework (MSTest) mit direkter Integration in VS2010 an. Sie können beispielsweise in eine Klasse gehen und mit Rechtsklick Unit-Tests erzeugen diese müssen Sie natürlich noch entsprechend ausprogrammieren. Die genauen Anweisungen für einen einfachen Testlauf können Sie dem Artikel Walkthrough: Creating and Running Unit Tests entnehmen. Die aus Java oder PHP bekannte Suite JUnit oder PHPUnit gibt es auch als.net-variante unter dem Namen NUnit. Es ist sicherlich sinnvoll, sich eines verbreiteten Frameworks zu bedienen, um sich nicht spezischen Besonderheiten eines ubiqutären Systems anzueignen. Die Assert-Api von NUnit ist umfangreicher als bei MSTest. Auÿerdem bietet NUnit eine gute Integration in CruiseControl und man kann eine Build-Umgebung unabhängig von Microsofts Team Foundation Servers aufsetzten. Dies ist insbesondere für die Zusammenarbeit mit einem Java-Team wichtig. NUnit soll auch performanter als MS-Test sein, was insbesondere bei Groÿprojekten relevant ist, da erst nach erfolgreichen Unit-Tests die Testabteilung anfangen kann. Um NUnit direkt aus VS2010 nutzen zu können, empehlt sich die Installation des Plugins TestDriven.Net oder die Verwendung des bereits erwähnten ReSharpener. Folgende Artikel bieten einen guten Vergleich zwischen MSTest und NUnit: Für diese Veranstaltung ist es Ihnen frei gestellt, welche Testumgebung Sie nutzen. 14 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

15 2.6 P1 - VS 2010: Einrichten und freies Erkunden der Arbeitsumgebung 2.6 P1 - VS 2010: Einrichten und freies Erkunden der Arbeitsumgebung Abgabetermin: Aufgabe P1.1 (Keine Abgabe) Starten Sie VS Erstellen Sie eine Console-Anwendung. Fügen Sie folgenden Code manuell in die Methode main ein: Console.WriteLine("started..."); string greeting="hi "; Console.WriteLine(greeting); for (int i = 0; i < 2; i++) Console.WriteLine(i.ToString()); Console.WriteLine("press any key to stop"); Console.ReadLine(); Listing 2.1: Erstes Programm (a) Schauen Sie sich die angebotenen Methoden bei Eingabe des Punktes an. (b) Markieren Sie das Wort Console und drücken Sie F12. (c) Führen Sie das Programm aus. (d) Debuggen Sie das Programm, fügen Sie Haltepunkte ein, beobachten Sie einzelne Variablen, gehen Sie schrittweise weiter. (e) Nutzen Sie Refactoring, um die Variable greeting umzubenennen. Aufgabe P1.2 Der Compiler erzeugt Ihnen eine Assembly. (a) Wo bendet sich die Datei? (b) Schauen Sie sich die Datei mit ildasm.exe (bendet sich in den SDK-Tools unter VS) an. (c) Verändern Sie in der Datei AssemblyInfo.cs die Einträge für Company und T itel. Wie wirkt sich dies aus? (d) Erzeugen Sie einmal eine Release-Version und einmal eine Debug-Version. Wodurch unterscheiden sich die Assemblies für diese Kongurationen? (e) Wählen Sie im Menü Projekt Ihre Projekteigenschaften aus. Wählen Sie nun Ressourcen und erstellen Sie eine neue Ressource. Geben Sie nun ein Variable-Wert-Paar ein. (f) Schauen Sie sich die erzeugte Datei Resources.Designer.cs an. (g) Wie können Sie die eben erzeugte Ressource auf der Console ausgeben? (h) Compilieren Sie das Projekt und schauen Sie sich erneut das erzeugte Assembly an. (i) Welche Informationen werden in der Assembly in welcher Form gespeichert? Aufgabe P1.3 (Keine Abgabe) Erstellen Sie eine einfache WPF-Applikation, die bei Drücken eines Knopfes den Inhalt eines Labels verändert. Die Grundlagen hierfür sind eigentlich noch nicht gelegt, jedoch ist die Bedienung recht intuitiv und Sie sollen bei dieser Aufgabe explorativ mit VS 2010 arbeiten. Aufgabe P1.4 In den Praktika P1-P6 entwickeln Sie schrittweise einen Audio-Player, dieser soll folgenden Anforderungen genügen: Es ist möglich, Playlists anzulegen, zu laden und abzuspeichern. Die Architektur soll es ermöglichen, Audio-, Video- und Bilddateien abzuspielen. Sie implementieren jedoch nur einen Audioplayer. Eine Playlist, kann abgespielt, angehalten, beendet werden. Es ist möglich, die Lautstärke zu regeln und eine Playlist kann auch zufällig abgespielt werden. Zu einer Playlist können Audio-Dateien hinzugefügt oder entfernt werden. 15 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

16 2.6 P1 - VS 2010: Einrichten und freies Erkunden der Arbeitsumgebung Beim Start wird die zuletzt verwendete Playlist geladen, das Abspielen beginnt an der entsprechenden Stelle. Sie können automatisch alle Audio-Dateien eines frei wählbaren Verzeichnisses hinzufügen. Dies erfolgt asynchron im Hintergrund. Setzen Sie sich mit der Aufgabestellung auseinander. Identizieren Sie Inkonsistenzen oder oene Punkte und klären Sie die Fragen mit Ihrem Betreuer. Erarbeiten Sie eine Liste von kurzen und informellen Anwendungsfällen (User Stories d.h. Überschrift + ein bis zwei Sätze). Dokumentieren Sie zu jeder User Story mit mindestens einem Test, wie Sie überprüfen wollen, dass die Funktionalität umgesetzt wurde. Erstellen Sie eine Skizze der Anwendungsoberäche. 16 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

17 3 C# kompakt Lernziele: Bisher bekannte OO-Elemente in C# wieder nden. Sprachbesonderheiten kennen lernen, sinnvoll einsetzen können und mit Lösungsmodellen anderer Programmiersprachen vergleichen. VS2010 sinnvoll und eektiv einsetzen. Die folgenden Beispiele zeigen die Syntax von C# exemplarisch. In den Unterabschnitten werden Besonderheiten der Sprache dargestellt. Der dazugehörige Text und die Beispiele stammen teilweise aus dem C#-Programmierhandbuch von Microsoft. 3.1 Syntax //Klasse Konstruktoren using System; / Blockkommentar / abstract class Shape public const double pi = Math.PI; protected double x, y, z; Listing 3.1: C# Grundlagen public Shape (double x, double y, double z) this.x = x; this.y = y; this.z = z; public abstract double Area(); class Circle: Shape public Circle(): this(100) //default radius is 100 public Circle(double radius): base(radius,0,0) public override double Area() return pi*x*x; class Cylinder: Circle public Cylinder(double radius, double height): base(radius) y = height; public override double Area() return 2*(base.Area()) + 2*pi*x*y; class TestClass 17

18 3.1 Syntax public static void Main() double radius = 2.5, height = 3.0; Circle mycircle = new Circle(radius); Cylinder mycylinder = new Cylinder(radius, height); Console.WriteLine("Area of the circle = 0:F2", mycircle.area()); Console.WriteLine("Area of the cylinder = 0:F2", mycylinder.area()); // versiegelte Klassen = nal in Java public sealed class D // Class members here. //statische Klassen public static class TemperatureConverter public static double CelsiusToFahrenheit(string temperaturecelsius)... double F, C = 0; F = TemperatureConverter.CelsiusToFahrenheit(Console.ReadLine()); // Schnittstellen public interface IStudentProvider void Add(Student student); int Count get; class DbStudentProvider: IStudentProvider private int _count; //... public DbStudentProvider() _count = 0; //... public void Add(Student student) // public int Count get return _count; //If Statement if (condition) / code / else if (othercondition) / code / else / code / //switch geht auch mit String int cost = 0; switch(n) case 1: cost += 25; 18 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

19 3.1 Syntax break; case 2: cost += 25; goto case 1; case 3: cost += 50; goto case 1; default: Console.WriteLine("Invalid selection. Please select 1, 2, or 3."); break; //For Schleife int[] myarray; for (int i = 0; myarray.length; i++) Console.WriteLine(myArray[i]); //Foreach Schleife int[] myarray; foreach (int element in myarray) Console.WriteLine(element); //Arrays // Declare a single dimensional array int[] array1 = new int[5]; // Declare and set array element values int[] array2 = new int[] 1, 3, 5, 7, 9 ; // Alternative syntax int[] array3 = 1, 2, 3, 4, 5, 6 ; // Declare a two dimensional array int[,] multidimensionalarray1 = new int[2, 3]; // Declare and set array element values int[,] multidimensionalarray2 = 1, 2, 3, 4, 5, 6 ; // Declare a jagged array int[][] jaggedarray = new int[6][]; // Set the values of the rst array in the jagged array structure jaggedarray[0] = new int[4] 1, 2, 3, 4 ; Frage 3.1 Fügen Sie in obigen Code den dazu gleichwertigen Code einer anderen OO-Sprache ein, z.b. Java. Markieren Sie Besonderheiten von C#. Frage 3.2 Werden Interfaces nur in Sprachen benötigt und eingesetzt, die keine Mehrfachvererbung unterstützen? Frage 3.3 Suchen Sie in.net nach 3 verschiedenen vordenierten Interfaces und beschreiben Sie deren Bedeutung. 19 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

20 3.1 Syntax Ähnlich wie in anderen OO-Sprachen gibt es die Zugrismodizierer private, public und protected. C# unterstützt auch internal. 1 public Auf den Typ oder Member kann von jedem Code in der gleichen Assembly siehe Abschnitt auf Seite 8 oder einer anderen Assembly, die darauf verweist, zugegrien werden. private Auf den Typ oder Member kann nur von Code in der gleichen Klasse oder Struktur zugegrien werden. protected Auf den Typ oder Member kann nur von Code in der gleichen Klasse oder Struktur oder in einer abgeleiteten Klasse zugegrien werden. internal Auf den Typ oder Member kann von jedem Code in der gleichen Assembly zugegrien werden, jedoch nicht von Code in einer anderen Assembly. protected internal Auf den Typ oder Member kann von jedem Code in der gleichen Assembly oder von jeder abgeleiteten Klasse in einer anderen Assembly zugegrien werden. Frage 3.4 Beschreiben Sie public, private, internal und protected in eigenen Worten und nennen Sie jeweils einen sinnvollen Nutzungsbereich. Methoden und Konstruktoren können überladen werden, ebenso können die meisten Operatoren überladen werden: Arithmetische, Vergleichs-, Logik- und Bedingungsoperatoren. Ausnahmen sind Zuweisungsoperatoren, Spezialoperatoren wie sizeof, new, is und typeof is vs as Mit is können Sie überprüfen, ob ein Objekt eine Instanz von einer bestimmten Klasse ist. Das Ergebnis ist ein Boolean-Wert. Mit as erhält man direkt das gecastete Objekt bwz. null, falls dies nicht möglich ist. Frage 3.5 Wie verhalten sich as und is bei abgeleiteten Klassen, d.h. was liefert Circle c = new Circle(3.0); Shape s; if (c is Shape) Console.WriteLine("Circle is Shape."); s = c as Shape; Console.WriteLine(s.Area().ToString()); if (s is Circle) Console.WriteLine("Shape is Circle."); c = s as Circle; Console.WriteLine(c.Area().ToString()); Listing 3.2: is und as 1 Zugrismodizierer 20 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

21 3.2 Typen Frage 3.6 Wie unterscheiden sich is/as und Casting? Operatoren In Bezug auf Operatoren möchte ich auch noch auf den tertiären Operator? mit : hinweisen, den es auch in anderen Programmiersprachen wie z.b. PHP gibt. Ähnlich dazu, gibt es den?? Operator. Dieser ist äuÿerst hilfreich, wenn Objekte auf null hin überprüft werden sollen. Es wird die Linke Seite evaluiert. Ist diese nicht null, wird der linke Wert zurückgegeben, andernfalls der rechte. Listing 3.3: Operatoren //Variante mit Bedingung?Wahrfall:Falschfall; string r = ( v == null )? "null" : v; //Variante mit dem?? Operator: string r = v?? "null"; //+ einmal anders class Matrix... Matrix operator +(Matrix l, Matrix r) Matrix e = new Matrix(); e = l mit r verknüpfen return e;... Matrix a = new Matrix(...), b = new Matrix(...); Matrix c = a + b; Frage 3.7 Gibt es auÿerhalb von mathematischen Objekten sinnvolle Anwendungsmöglichkeiten für Operatoren? Wenn ja, wo? Partial Die Denitionen partieller Typen ermöglichen es, die Denition einer Klasse, einer Struktur oder einer Schnittstelle auf mehrere Dateien aufzuteilen. Einen Klassen-, Struktur- oder Schnittstellentyp auf mehrere Dateien aufzuteilen kann hilfreich sein, wenn Sie mit groÿen Projekten oder mit automatisch generiertem Code wie z.b. von Der Windows Forms-Designer bereitgestellt. Verwenden Sie hierfür das Schlüsselwort partial, also z.b. partial class A in zwei Dateien. Frage 3.8 Gibt es das Prinzip von Partial auch in Java oder PHP? 3.2 Typen CTS Das Common Type System (CTS) ist die Gesamtmenge aller möglichen Eigenschaften und Typen (siehe Abbildung 5.3). Die Common Language Specication (CLS) ist eine Untermenge der CTS-Eigenschaften und Typen, 21 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

22 3.2 Typen Abbildung 3.1: CTS nach ECMA-335 die von jedem Compiler unterstützt werden müssen, um die Interoperabilität zwischen der.net Applikationen zu garantieren. Nicht CLS-konforme Typen sind beispielsweise Int8 oder Unsigned int64. Die CLS stellt einen Satz von Merkmalen sicher, die in jeder Sprache, die in die Laufzeitumgebung integriert wird, garantiert zur Verfügung stehen. Die CLS garantiert, dass jedes Programm bzw. jeder Programmteil (z. B. eine einzelne Klasse), der CLS-konform entwickelt worden ist, in jeder anderen CLS-kompatiblen Programmiersprache vollständig genutzt werden kann 2. Beispielsweise gibt es nur einen unicode-basierten Stringtyp und alles ist ein Objekt. Dadurch ist die.net Plattform selbst sprachneutral und jede der dort verwendeten Sprachen ist gleich berechtigt. Betrachtet man das CTS, also die Gesamtzahl aller Typen, so kann man diese für C# wie in Abbildung 3.2 gruppieren vergleiche hierzu auch Abbildung 3.1. Die Bezeichnung ValueType hat nichts mit der Parameterübergabe byref bzw. byval zu tun. Zwischen den einfachen Typen gibt es die typischen impliziten Konvertierungen. Wir erinnern uns daran, dass alle Typen in C# von object abgeleitet sind. Dies erönet uns zusätzliche Möglichkeiten: Jeder Datentyp kann als Objekt gespeichert oder übergeben werden. Der Boxing Vorgang beschreibt die Umwandlung von einem value-type zu einem Objekt. Bei dem Boxing Vorgang wird die Instanz eines Objekts erstellt und der ursprüngliche Wert des value-types wird in das neue Objekt kopiert. Man könnte sagen, dies sei der umgekehrte Vorgang. Beim Unboxing Vorgang wird ein value type aus einem Objekt extrahiert. Der C# Compiler überprüft zusätzlich, ob die von Ihnen angeforderte Variable, welche Sie aus dem Objekt extrahieren wollen, tatsächlich den angeforderten unboxed Type entsprechen kann. Boxing und Unboxing ist ein zentraler Teil im Type-System von C# (und der Runtime). Es stellt ein Bindeglied zwischen value-types und reference-types zur Verfügung. Value-types haben den Vorteil, dass sie wenig Speicherplatz benötigen. In manchen Fällen ist es jedoch von Vorteil, dass value-types auch die die Eigenschaften von Objekten haben. 2 Die Regeln der CLS gelten dabei immer nur für öentliche (public oder protected) Schnittstellen. 22 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

23 3.2 Typen Abbildung 3.2: Typen im Namespace System Abbildung 3.3: Boxing und Unboxing nach ECMA 335 Merke 3 (Werttypen) Es gibt Werttypen für Zahlen mit verschiedenen Gröÿen und Genauigkeiten. Eine gröÿere Zahl oder eine Zahl mit einer höheren Genauigkeit braucht mehr Speicher auf dem Stack. Jeder Werttyp hat eine Gröÿe. Es ist nicht möglich, einen Wert eines gröÿeren Typs in eine kleinere Variable zu stecken, unabhängig davon, wie groÿ die Zahl tatsächlich ist Strukturen Klassen und Strukturen sind zwei der grundlegenden Konstrukte des allgemeinen Typsystems in.net Framework. Bei beiden handelt es sich um eine Datenstruktur, die einen als logische Einheit zusammengehörenden Satz von Daten und Verhalten kapselt. Die Daten und Verhalten sind die Member der Klasse oder Struktur. Diese enthalten deren Methoden, Eigenschaften, Ereignisse usw. Eine Struktur ist ein Werttyp. Wenn eine Struktur erstellt wird, enthält die Variable, der die Struktur zugewiesen wird, die eigentlichen Daten der Struktur. Wenn die Struktur einer neuen Variable zugewiesen wird, werden diese kopiert. Die neue Variable und die ursprüngliche Variable enthalten daher zwei separate Kopien der gleichen Daten. Änderungen an einer Kopie wirken sich nicht auf die andere Kopie aus. Im Allgemeinen werden Klassen zum Modellieren von komplexerem Verhalten oder von Daten verwendet, die dafür vorgesehen sind, nach der Erstellung eines Klassenobjekts geändert zu werden. Strukturen sind am besten für kleine Datenstrukturen geeignet, die überwiegend Daten enthalten, deren Änderung nach der Erstellung der Struktur nicht vorgesehen ist. Besonderheiten von Strukturen im Vergleich zu Klassen: Strukturen haben fast die gleiche Syntax wie Klassen, unterliegen jedoch mehr Beschränkungen als Klassen: Innerhalb einer Strukturdeklaration können Felder nur dann initialisiert werden, wenn sie als konstant oder statisch deklariert werden. 23 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

24 3.2 Typen Eine Struktur kann keinen Standardkonstruktor (ein Konstruktor ohne Parameter) und keinen Destruktor deklarieren. Eine Struktur ist nicht in der Lage, von einer anderen Struktur oder Klasse zu erben, und sie kann auch nicht die Basis einer Klasse sein. Alle Strukturen erben direkt von System.ValueType, welcher von System.Object erbt. Strukturen werden durch Zuweisung kopiert. Wenn eine Struktur einer neuen Variablen zugewiesen wird, werden alle Daten kopiert. Änderungen an der neuen Kopie wirken sich nicht auf die Daten in der ursprünglichen Kopie aus. Strukturen sind Werttypen, und Klassen sind Referenztypen. Strukturen können im Gegensatz zu Klassen ohne einen Operator new instanziiert werden. Eine Struktur kann Schnittstellen implementieren. Listing 3.4: Beispiel für Strukturen public struct Coords public int x, y; public CoOrds(int p1, int p2) x = p1; y = p2; Merke 4 (struct/objekt Parameterübergabe) Da Strukturen Werttypen sind und Objekte Referenztypen sind, gilt: Wenn struct an eine Methode übergeben wird, wird eine Kopie der Struktur übergeben. Bei der Übergabe einer class-instanz wird jedoch ein Verweis übergeben Strings Eine Zeichenfolge ist ein Objekt vom Typ String, dessen Wert Text ist. Intern wird der Text als schreibgeschützte Auistung von Char-Objekten gespeichert, von denen jedes ein in UTF-16 codiertes Unicode-Zeichen darstellt. Eine C#-Zeichenfolge wird nicht mit einem NULL-Zeichen am Ende terminiert (im Gegensatz zu C und C++). Deshalb kann eine C#-Zeichenfolge eine beliebige Anzahl eingebetteter NULL-Zeichen (' 0') enthalten. Die Länge einer Zeichenfolge stellt die Anzahl der Zeichen unabhängig davon dar, ob die Zeichen aus Unicode-Ersatzzeichenpaaren gebildet werden oder nicht. Um in einer Zeichenfolge auf die einzelnen Unicode-Codepunkte zuzugreifen, verwenden Sie das StringInfo-Objekt. In C# ist das string-schlüsselwort ein Alias für String. Deshalb entsprechen sich String und string, und Sie können eine beliebige Namenskonvention verwenden. Die String-Klasse stellt viele Methoden zum sicheren Erstellen, Bearbeiten und Vergleichen von Zeichenfolgen bereit. Initialisieren Sie eine Zeichenfolge mit dem konstanten Empty-Wert, um ein neues String-Objekt zu erstellen, dessen Zeichenfolge die Länge NULL aufweist. Durch die Initialisierung von Zeichenfolgen mit dem Wert Empty anstelle von null können Sie die Chancen einer NullReferenceException reduzieren. Verwenden Sie die statische IsNullOrEmpty(String)-Methode, um den Wert einer Zeichenfolge zu prüfen, bevor Sie versuchen, darauf zuzugreifen. Da eine Zeichenfolgenänderung einer neuen Zeichenfolgenerstellung gleichkommt, müssen Sie beim Erstellen von Verweisen auf Zeichenfolgen vorsichtig sein. Wenn Sie einen Verweis auf eine Zeichenfolge erstellen und dann die ursprüngliche Zeichenfolge ändern, zeigt der Verweis weiterhin auf das ursprüngliche Objekt und nicht auf das neue Objekt, das beim Ändern der Zeichenfolge erstellt wurde. Der folgende Code veranschaulicht dieses Verhalten: 24 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

25 3.2 Typen string s1 = "Hello "; string s2 = s1; s1 += "World"; Listing 3.5: Stringreferenz System.Console.WriteLine(s2); //Output: Hello string s1 = "Hello "; string s2 = s1; s1 = "Hello World"; System.Console.WriteLine(s2); Listing 3.6: Stringreferenz Frage 3.9 Was wird in Listing 3.6 ausgegeben? Längere Strings oder Pfade können Sie in C# mit einem denieren. string path string quote name was ""Sara."""; string minitemplate 0, Your friend 1 sent you this message: 2 That's all!"; Listing 3.7: Strings - ähnlich Heredoc von PHP string populatedtemplate = String.Format(miniTemplate, "Fred", "Jack", "HelloWorld!"); System.Console.WriteLine(populatedTemplate); Generika Manchmal möchte man eine Klasse oder Parameter einer Methode so allgemein halten, dass sie mit Objekten verschiedener Typen arbeiten können. Dies könnte man durch den allgemeinsten Datentyp Object erreichen, damit können Typen jedoch gemischt werden. Möchte man auf Typsicherheit nicht verzichten, so kann man Generika einsetzen. Häug verwendet man generische Listen, um z.b. Stringlisten, Int-Listen oder Listen von Objekten einer Klasse zu verarbeiten. Listing 3.8: Generika public class GenericList<T> void Add(T input) class TestGenericList private class ExampleClass static void Main() GenericList<int> list1 = new GenericList<int>(); GenericList<string> list2 = new GenericList<string>(); GenericList<ExampleClass> list3 = new GenericList<ExampleClass>(); //generische Interfaces interface IEquatable<T> bool Equals(T obj); public class Car : IEquatable<Car> //weitere implementierte Interfaces durch, abtrennen 25 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

26 3.2 Typen private string make; private string model; public string Make get return make; set make = value; public string Model get return model; set model = value; // Implementation of IEquatable<T> interface public bool Equals(Car car) if (this.make == car.make && this.model == car.model) return true; else return false; Listen Abbildung 3.4: Listen Abbildung 3.4 stellt wesentliche Listen des Namensraums System.Collection mit den von ihnen implementierten Interfaces dar. Hashtable stellt eine Auistung von Schlüssel-Wert-Paaren dar, die nach dem Hashcode des Schlüssels organisiert sind. Die generische Dictionary<(Of <(TKey, TValue>)>)-Klasse stellt eine Zuordnung von einem Satz von Schlüsseln zu einem Satz von Werten bereit. Jede Hinzufügung zum Wörterbuch besteht aus einem Wert und dem zugeordneten Wenn ein Objekt im Dictionary<(Of <(TKey, TValue>)>) als Schlüssel verwendet wird, darf es nicht auf eine Weise geändert werden, die sich auf seinen Hashwert auswirkt. Jeder Schlüssel in einem Dictionary<(Of <(TKey, TValue>)>) muss für den Gleichheitsvergleich des Wörterbuches eindeutig sein. ArrayList implementiert die IList-Schnittstelle unter Verwendung eines Arrays, das nach Bedarf dynamisch vergröÿert wird. Es wird nicht sichergestellt, dass die ArrayList sortiert ist. Sie müssen die ArrayList sortieren, bevor Sie Vorgänge wie BinarySearch durchführen, die eine sortierte ArrayList voraussetzen. Die List<(Of <(T>)>)-Klasse stellt die generische Entsprechung der ArrayList-Klasse dar. Sie implementiert die generische IList<(Of <(T>)>)-Schnittstelle unter Verwendung eines Arrays, das nach Bedarf dynamisch vergröÿert wird. Queue stellt eine FIFO-Auistung (First-In-First-Out) von Objekten dar. Stack stellt eine LIFO (Last-In-First-Out)-Auistung variabler Gröÿe von Instanzen desselben beliebigen Typs dar. Hashtable openwith = new Hashtable(); openwith.add("txt", "notepad.exe"); Listing 3.9: Listen 26 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

27 3.2 Typen Dictionary<string, string> openwith2 = new Dictionary<string, string>(); openwith2.add("txt", "notepad.exe"); ArrayList myal = new ArrayList(); myal.add("hello"); List<string> dinosaurs = new List<string>(); dinosaurs.add("tyrannosaurus"); Queue<string> numbers = new Queue<string>(); numbers.enqueue("one"); Stack<string> numbers = new Stack<string>(); numbers.push("one"); Frage 3.10 Diskutieren Sie mögliche Probleme bei folgendem Code: List<string> ls = new List<string>(); List<object> lo = ls; lo.add(new Object()); string s = ls.get(0); Enumerationen Ein Enumerationstyp (auch als Enumeration bezeichnet) bietet eine eziente Möglichkeit, einen Satz benannter integraler Konstanten zu denieren, die einer Variablen zugewiesen werden können. Angenommen, Sie müssen eine Variable denieren, deren Wert einen Wochentag darstellt. Es gibt nur sieben sinnvolle Werte, die diese Variable speichern kann. Um diese Werte zu denieren, können Sie einen Enumerationstyp verwenden, der durch die Verwendung des enum-schlüsselworts deklariert wird. Der zugrunde liegende Standardtyp aller Elemente in der Enumeration lautet int. Listing 3.10: Enumerationen enum Days Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday ; enum Months : byte Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec ; Days meetingday = Days.Monday; enum MachineState PowerOff = 0, Running = 5, Sleeping = 10, Hibernating = Sleeping + 5 Sie können einen Enumerationstyp verwenden, um Bitags zu denieren. Dadurch kann eine Instanz des Enumerationstyps eine Kombination aus den Werten speichern, die in der Enumeratorliste deniert sind. Im folgenden Beispiel wird eine andere Version des Days-Enumerators, der als Days2 bezeichnet ist, deniert. Days2 weist das Flags-Attribut auf, und jedem Wert wird die nächste höhere Potenz von 2 zugewiesen. So können Sie eine Days2-Variable erstellen, deren Wert Days2.Tuesday und Days2.Thursday lautet. Um ein Flag eines Enumerators festzulegen, verwenden Sie den logischen OR-Operator. Um zu ermitteln, ob ein bestimmtes Flag festgelegt ist, verwenden Sie eine logische AND-Operation. 27 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

28 3.3 Attribute und Reektion [Flags] enum Days2 None = 0x0, Sunday = 0x1, Monday = 0x2, Tuesday = 0x4, Wednesday = 0x8, Thursday = 0x10, Friday = 0x20, Saturday = 0x40 class MyClass Days2 meetingdays = Days2.Tuesday Days2.Thursday; private void pleassure() // Initialize with two ags using bitwise OR. meetingdays = Days2.Tuesday Days2.Thursday; // Set an additional ag using bitwise OR. meetingdays = meetingdays Days2.Friday; Listing 3.11: Enumeration als Flags Console.WriteLine("Meeting days are 0", meetingdays); // Output: Meeting days are Tuesday, Thursday, Friday // Remove a ag using bitwise XOR. meetingdays = meetingdays ^ Days2.Tuesday; Console.WriteLine("Meeting days are 0", meetingdays); // Output: Meeting days are Thursday, Friday // Test value of ags using bitwise AND. bool test = (meetingdays & Days2.Thursday) == Days2.Thursday; Console.WriteLine("Thursday 0 a meeting day.", test == true? "is" : "is not"); // Output: Thursday is a meeting day. Frage 3.11 Welche anderen Programmiersprachen kennen Generika? Frage 3.12 Diskutieren Sie folgende Aussage: Generische typsichere Listen sind einer ArrayList immer vor zu ziehen. 3.3 Attribute und Reektion Attribute stellen eine eziente Methode dar, um Deklarationsinformationen mit C#-Code (Typen, Methoden, Eigenschaften usw.) zu verknüpfen. Sobald das Attribut einer Programmentität zugeordnet ist, kann es zur Laufzeit mithilfe eines Verfahrens abgefragt werden, das als Reektion bezeichnet wird Attribute Attribute fügen dem Programm Metadaten hinzu. Metadaten sind Informationen zu den in einem Programm denierten Typen. Alle.NET-Assemblys enthalten einen angegebenen Satz von Metadaten, die die in der Assembly denierten Typen und Typmember beschreiben. Sie können benutzerdenierte Attribute hinzufügen, um bei Bedarf zusätzliche Informationen anzugeben. Sie können eigene benutzerdenierte Attribute erstellen, indem Sie eine Attributklasse denieren. Dies ist eine Klasse, die direkt oder indirekt Elemente von Attribute ableitet, wodurch die schnelle und einfache Identikation 28 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

29 3.3 Attribute und Reektion von Attributdenitionen in Metadaten ermöglicht wird. Angenommen, Sie möchten Klassen und Strukturen mit dem Namen des Programmierers kennzeichnen, der sie geschrieben hat. Sie könnten beispielsweise eine benutzerdenierte Author-Attributklasse denieren: Der Klassenname entspricht dem Attributnamen, also Author. Da er von System.Attribute abgeleitet ist, handelt es sich um eine benutzerdenierte Attributklasse. Die Parameter des Konstruktors sind die positionellen Parameter des benutzerdenierten Attributs (in diesem Fall name), und alle öentlichen Felder oder Eigenschaften, die Lese- und Schreibzugri unterstützen, sind benannte Parameter (in diesem Fall ist version der einzige benannte Parameter). Beachten Sie, dass das AttributeUsage-Attribut verwendet wird, um die Gültigkeit des Author-Attributs auf class- und struct-deklarationen zu beschränken Reektion Metadaten eines Moduls können zur Laufzeit ausgelesen und geändert werden Diesen Vorgang nennt man Reektion.NET Framework stellt entsprechende Klassen über den Namespace System.Reection bereit 3 Bei der Reektion werden Objekte (vom Typ Type) bereitgestellt, die Assemblys, Module und Typen beschreiben. Mithilfe von Reektion können Instanzen von Typen dynamisch erzeugt, Typen an ein vorhandenes Objekt gebunden und Typinformationen von vorhandenen Objekten abgefragt werden. Ebenso können die Methoden vorhandener Objekte aufgerufen werden, und es kann auf ihre Felder und Eigenschaften zugegrien werden. Wenn Sie Attribute im Code verwenden, können Sie mithilfe von Reektion auf diese Attribute zugreifen. Reektion ist in folgenden Situationen nützlich: Wenn Sie auf Attribute in den Metadaten des Programms zugreifen müssen. Für das Überprüfen und das Instanziieren von Typen in einer Assembly. Für das Erstellen neuer Typen zur Laufzeit. Verwenden Sie die Klassen in System.Reection.Emit. Für das Ausführen von spätem Binden und für den Zugri auf Methoden von zur Laufzeit erstellten Typen. Zugri auf Attribute mit Reektion Listing 3.12: Benutzerdeniertes Attribute und Reektion //Denition [System.AttributeUsage(System.AttributeTargets.Class System.AttributeTargets.Struct, AllowMultiple = true) // multiuse attribute ] public class Author : System.Attribute string name; public double version; public Author(string name) this.name = name; version = 1.0; // Default value public string GetName() return name; [Author("H. Ackerman")] private class FirstClass //... // No Author attribute private class SecondClass //... 3 Reektion 29 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

30 3.3 Attribute und Reektion [Author("H. Ackerman"), Author("M. Knott", version = 2.0)] private class ThirdClass //... class TestAuthorAttribute static void Main() PrintAuthorInfo(typeof(FirstClass)); PrintAuthorInfo(typeof(SecondClass)); PrintAuthorInfo(typeof(ThirdClass)); private static void PrintAuthorInfo(System.Type t) System.Console.WriteLine("Author information for 0", t); System.Attribute[] attrs = System.Attribute.GetCustomAttributes(t); // reection foreach (System.Attribute attr in attrs) if (attr is Author) Author a = (Author)attr; System.Console.WriteLine(" 0, version 1:f", a.getname(), a.version); Frage 3.13 Welche Ausgabe erzeugt das Programm? Frage 3.14 Suchen Sie drei Anwendungsfälle, in denen Attribute und Reektions eingesetzt werden Performance Zeichenfolgenobjekte sind unveränderlich (immutable). Das bedeutet, dass sie nicht mehr geändert werden können, nachdem sie erstellt wurden. Alle String-Methoden und C#-Operatoren, mit denen eine Zeichenfolge geändert werden könnte, geben diese Ergebnisse in einem neuen Zeichenfolgenobjekt zurück. Im folgenden Beispiel bleiben beim Verketten des Inhalts von s1 und s2 zu einer einzelnen Zeichenfolge die beiden ursprünglichen Zeichenfolgen unverändert. Der Operator += erstellt eine neue Zeichenfolge, die die kombinierten Inhalte enthält. Dieses neue Objekt wird der Variablen s1 zugewiesen. Das ursprüngliche Objekt, das s1 zugewiesen wurde, wird für die Garbage Collection freigegeben, da keine andere Variable einen Verweis darauf enthält. Mit der Klasse StringBuilder können Sie ohne das Zerstören und Neuerstellen von Objekten speicherezient Zeichenketten zusammenführen. Die Klasse enthält auch weitere nützliche Methoden. int x = 4; StringBuilder sb = new StringBuilder(); sb.append(x.tostring()); sb.appendformat("ghi01", 'J', 'k'); sb.append(" und "); //Einen Text am Anfang einfügen sb.insert(0, "Alphabet: "); Listing 3.13: StringBuilder zur Verkettung von Strings 30 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

31 3.3 Attribute und Reektion sb.replace('k', 'K'); Console.WriteLine("0 chars: 1", sb.length, sb.tostring()); Noch eine Performanceverbesserung gibt es beim Prüfen auf Leerstrings: Der Vergleich von Zeichenfolgen mit der System.String.Length-Eigenschaft oder der System.String.IsNullOrEmpty(System.String)-Methode ist bedeutend schneller als ein Vergleich mit Equals. string s1 = "test"; //nicht performant if (s1 == "") if (!String.IsNullOrEmpty(s1) ) Console.WriteLine("s1!= null and s1.length!= 0."); Listing 3.14: String auf leer prüfen Neben StringBuilder und dem Prüfen auf Leerstrings gibt es weitere Möglichkeiten, Code performanter zu schreiben. Wenn Sie ein Feld als static und readonly deklarieren und mit einem Wert initialisieren, dann sollten Sie stattdessen const verwenden. Der Wert eines const-felds wird zur Kompilierungszeit berechnet und in den Metadaten gespeichert. Dadurch wird im Vergleich zu einem static readonly-feld die Laufzeitleistung gesteigert. Wenn mit dem is-operator von C# getestet wird, ob die Umwandlung erfolgreich durchgeführt werden kann, bevor die eigentliche Umwandlung erfolgt, sollten Sie erwägen, stattdessen das Ergebnis des as-operators zu testen. Dieses Vorgehen bietet die gleiche Funktionalität ohne die implizite vom is-operator ausgeführte Umwandlungsoperation. // The 'is ' statement performs a cast operation. if(obj is Control) // The 'as' statement performs a duplicate cast operation. Control acontrol = obj as Control; // Use acontrol. //besser: Control acontrol = obj as Control; if(acontrol!= null) // Use acontrol. Listing 3.15: is/as performant einsetzen Zur Analyse Ihres Codes, können Sie eine hilfreiche Eigentschaft Ihres Projekts setzen: Option Codeanalyse aktivieren. Weitere Empfehlungen zur Erstellung von hochwertigem Code nden Sie unter Verfassen von qualitativ hochwertigem Quellcode und darin insbesondere Leistungswarnungen IList, IEnumerable und andere Interfaces Möchte man eine Klasse mit foreach durchlaufen, so benötigt man die Methode GetEnumerator. Listing 3.16: Iteratoren public class DaysOfTheWeek : System.Collections.IEnumerable string[] days = "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" ; public System.Collections.IEnumerator GetEnumerator() for (int i = 0; i < days.length; i++) yield return days[i]; class TestDaysOfTheWeek static void Main() // Create an instance of the collection class 31 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

32 3.3 Attribute und Reektion DaysOfTheWeek week = new DaysOfTheWeek(); // Iterate with foreach foreach (string day in week) System.Console.Write(day + " "); Im obigen Listing taucht ein bisher nicht eingeführtes Schlüsselwort auf, yield. In der ausführlichen Anleitung für Iteratoren ndet sich bei Microsoft hierzu Durch die yield return-anweisung wird ein Element in der Quellsequenz unverzüglich an den Aufrufer zurückgegeben, noch bevor auf das nächste Element in der Quellsequenz zugegrien wird.. IEnumerator ist das Basisinterface für alle Collections, es erlaubt das Lesen von Daten, jedoch keinen schreibenden Zugri, also keinen Zugri auf die Referenz der ihm zugrundeliegenden Collection. IEnumerable beinhaltet nur die Methode GetEnumerator. IEnumerator enthält die Methoden MoveNext, Current und Reset. Das Durchlaufen einer foreach-schleife ist nun mit dem Cursororientierten Lesen in einer Datenbank vergleichbar: Nach jeder Iteration wird MoveNext aufgerufen und Current entsprechend gesetzt. Ist das Ende erreicht, wird Reset automatisch aufgerufen. Von diesen Interfaces macht auch LINQ (siehe Abschnitt?? auf Seite??) intensiv Gebrauch. Frage 3.15 Welchen Wert hat eine Schleifen-Variable am Ende einer foreach-schleife? (1) null (2) letztes Element (3) erstes Element (4) keine, der genannten Möglichkeiten Ist es nicht nur notwendig, über Listenelemente zu iterieren, so bieten sich die Interfaces ICollection und IList an, bzw. deren generischen Varianten ICollection<> und IList<>. ICollection fügt Methoden wie Add und Remove und Eigenschaften wie Count und IsReadOnly hinzu. IList erbt von ICollection und fügt noch einen index-basierten Methoden hinzu. IComparable und IComparer Dieser Abschnitt stammt aus dem frei zugänglichen online verfügbaren Buch: C# von Eric Gunnerson Die neue Sprache für Microsofts.NET-Plattform. Die Frameworks halten für Klassen oder Strukturen einige sehr gute Methoden zur Sortierung der Klassenoder Strukturinstanzen bereit. Bei der einfachsten Methode implementiert das Objekt die IComparable- Schnittstelle: using System; public class Employee: IComparable public Employee(string name, int id) this.name = name; this.id = id; int IComparable.CompareTo(object obj) Employee emp2 = (Employee) obj; if (this.id > emp2.id) return(1); if (this.id < emp2.id) return(-1); else return(0); Listing 3.17: IComparable 32 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

33 3.3 Attribute und Reektion public override string ToString() return(string.format("0:1", name, id)); string name; int id; class Test public static void Main() Employee[] arr = new Employee[4]; arr[0] = new Employee("George", 1); arr[1] = new Employee("Fred", 2); arr[2] = new Employee("Tom", 4); arr[3] = new Employee("Bob", 3); Array.Sort(arr); foreach (Employee emp in arr) Console.WriteLine("Employee: 0", emp); Diese Implementierung ermöglicht lediglich eine Sortierung; die Klasse könnte so deniert werden, dass eine auf Mitarbeiter-ID oder Name basierende Sortierung vorgenommen wird, dem Benutzer kann jedoch die Auswahl der Sortierreihenfolge nicht ermöglicht werden. Die Designer der Frameworks haben die Fähigkeit zur Denition mehrerer Sortierreihenfolgen bereitgestellt. Jede Sortierreihenfolge wird durch die IComparer-Schnittstelle ausgedrückt, die geeignete Schnittstelle wird der Sortier- oder Suchfunktion übergeben. Die IComparer-Schnittstelle kann für Employee jedoch nicht implementiert werden, da jede Klasse eine Schnittstelle nur einmal implementieren kann. Es könnte also nur eine Sortierreihenfolge bereitgestellt werden1. Es ist für jede Sortierung eine separate Klasse erforderlich, die IComparer implementiert. Die Klasse ist sehr einfach, da nur die Compare()-Funktion implementiert wird: using System; using System.Collections; class Employee public string name; class SortByNameClass: IComparer public int Compare(object obj1, object obj2) Employee emp1 = (Employee) obj1; Employee emp2 = (Employee) obj2; Listing 3.18: IComparer return(string.compare(emp1.name, emp2.name)); Das Compare()-Mitglied trägt zwei Objekte als Parameter. Da die Klasse nur zur Mitarbeitersortierung eingesetzt werden sollte, werden die object-parameter per Typumwandlung zu Employee. Anschlieÿend wird die in string enthaltene Compare()-Funktion für den Vergleich verwendet. Die Employee-Klasse wird demnach folgendermaÿen überarbeitet. Die Klassen für die Sortierungen werden innerhalb der Employee-Klasse verschachtelt: using System; using System.Collections; public class Employee: IComparable public Employee(string name, int id) Listing 3.19: IComparable 33 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

34 3.3 Attribute und Reektion this.name = name; this.id = id; int IComparable.CompareTo(object obj) Employee emp2 = (Employee) obj; if (this.id > emp2.id) return(1); if (this.id < emp2.id) return(-1); else return(0); public override string ToString() return(name + ":" + id); public class SortByNameClass: IComparer public int Compare(object obj1, object obj2) Employee emp1 = (Employee) obj1; Employee emp2 = (Employee) obj2; return(string.compare(emp1.name, emp2.name)); public class SortByIdClass: IComparer public int Compare(object obj1, object obj2) Employee emp1 = (Employee) obj1; Employee emp2 = (Employee) obj2; return(((icomparable) emp1).compareto(obj2)); string name; int id; class Test public static void Main() Employee[] arr = new Employee[4]; arr[0] = new Employee("George", 1); arr[1] = new Employee("Fred", 2); arr[2] = new Employee("Tom", 4); arr[3] = new Employee("Bob", 3); Array.Sort(arr, (IComparer) new Employee.SortByNameClass()); // Mitarbeiter sind jetzt nach Name sortiert foreach (Employee emp in arr) Console.WriteLine("Employee: 0", emp); Array.Sort(arr, (IComparer) new Employee.SortByIdClass()); // Mitarbeiter sind jetzt nach ID sortiert foreach (Employee emp in arr) Console.WriteLine("Employee: 0", emp); ArrayList arrlist = new ArrayList(); arrlist.add(arr[0]); arrlist.add(arr[1]); arrlist.add(arr[2]); arrlist.add(arr[3]); arrlist.sort((icomparer) new Employee.SortByNameClass()); foreach (Employee emp in arrlist) 34 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

35 3.3 Attribute und Reektion Console.WriteLine("Employee: 0", emp); arrlist.sort(); // Standard = nach ID foreach (Employee emp in arrlist) Console.WriteLine("Employee: 0", emp); Frage 3.16 Warum wirft folgender Code eine Ausnahme? class Employee public string Name get; set; public int Salary get; set;... List<Employee> emplist = new List<Employee>() new Employee Name = "a", Salary = 14000, new Employee Name = "b", Salary = ; emplist.sort(); Und wie sieht es hiermit aus? IList<string> strings = new List<string>(); IList<object> objects = strings; objects[0] = 42; string s = strings[0]; IDisposable IDisposable deniert eine Methode zur Freigabe von reservierten Ressourcen. Über diese Schnittstelle werden hauptsächlich nicht verwaltete Ressourcen freigegeben. Der Garbage Collector gibt automatisch den für ein verwaltetes Objekt reservierten Speicher frei, wenn dieses Objekt nicht mehr verwendet wird. Es kann allerdings nicht vorausgesagt werden, wann die Garbage Collection stattndet. Darüber hinaus hat der Garbage Collector keine Kenntnis von nicht verwalteten Ressourcen wie Fensterhandles oder oenen Dateien und Streams. Mit der Dispose-Methode dieser Schnittstelle können nicht verwaltete Ressourcen in Verbindung mit dem Garbage Collector explizit freigegeben werden. Der Consumer eines Objekts kann diese Methode aufrufen, wenn das Objekt nicht mehr benötigt wird. Verwenden Sie für den Aufruf einer Klasse, die die IDisposable-Schnittstelle implementiert, einen try-nally-block, um sicherzustellen, dass nicht verwaltete Ressourcen auch dann freigegeben werden, wenn die Anwendung aufgrund einer Ausnahme beendet wird. Das Muster zum Verwerfen eines Objekts, Dispose-Muster genannt, legt eine Ordnung für die Lebensdauer von Objekten fest. Die Dispose-Methode eines Typs sollte alle Ressourcen freigeben, die dieser besitzt. Sie sollte auÿerdem alle Ressourcen freigeben, deren Eigentümer die Basistypen der Methode sind, indem die Dispose-Methode des übergeordneten Typs aufgerufen wird. Die Dispose-Methode des übergeordneten Typs sollte alle Ressourcen freigeben, die dieser besitzt, und dann die Dispose-Methode seines übergeordneten Typs aufrufen. Dieses Muster wird durch die Hierarchie der Basistypen weitergegeben. Um sicherzustellen, dass Ressourcen immer entsprechend bereinigt werden, sollte eine Dispose-Methode auch mehrmals aufgerufen werden können, ohne eine Ausnahme auszulösen. Durch das Implementieren der Dispose-Methode für Typen, die nur verwaltete Ressourcen (z. B. Arrays) verwenden, werden keine Leistungsvorteile erzielt, da diese automatisch vom Garbage Collector freigegeben werden. 35 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

36 3.3 Attribute und Reektion Verwenden Sie die Dispose-Methode primär für verwaltete Objekte, die systemeigene Ressourcen verwenden, und für COM-Objekte, die für.net Framework verfügbar sind. Verwaltete Objekte, die systemeigene Ressourcen (z. B. die FileStream-Klasse) verwenden, implementieren die IDisposable-Schnittstelle. Eine Dispose-Methode sollte die SuppressFinalize-Methode für das Objekt aufrufen, das es freigibt. Wenn sich das Objekt gegenwärtig in der Finalisierungswarteschlange bendet, verhindert SuppressFinalize, dass dessen Finalize-Methode aufgerufen wird. Beachten Sie, dass das Ausführen einer Finalize-Methode hohen Leistungsaufwand erfordert. Wenn Sie das Objekt bereits mit der Dispose-Methode bereinigt haben, muss die Finalize- Methode des Objekts nicht mehr vom Garbage Collector aufgerufen werden. Im folgenden Codebeispiel wird das empfohlene Entwurfsmuster für das Implementieren einer Dispose-Methode für Klassen veranschaulicht, die nicht verwaltete Ressourcen kapseln. Ressourcenklassen werden i. d.r. von komplexen systemeigenen Klassen oder APIs abgeleitet und müssen entsprechend angepasst werden. Verwenden Sie dieses Codemuster als Anfangspunkt zum Erstellen einer Ressourcenklasse, und stellen Sie die erforderliche Anpassung basierend auf den Ressourcen, die Sie kapseln, bereit. //Klasse, die IDisposable implementiert. public class DisposableResource : IDisposable private Stream resource; private bool disposed; Listing 3.20: Dispose-Pattern // The stream passed to the constructor // must be readable and not null. public DisposableResource(Stream stream) if (stream == null) throw new ArgumentNullException("Stream in null."); if (!stream.canread) throw new ArgumentException("Stream must be readable."); resource = stream; disposed = false; // Demonstrates using the resource. // It must not be already disposed. public void DoSomethingWithResource() if (disposed) throw new ObjectDisposedException("Resource was disposed."); // Show the number of bytes. int numbytes = (int) resource.length; Console.WriteLine("Number of bytes: 0", numbytes.tostring()); public void Dispose() Dispose(true); // Use SupressFinalize in case a subclass // of this type implements a nalizer. GC.SuppressFinalize(this); protected virtual void Dispose(bool disposing) // If you need thread safety, use a lock around these // operations, as well as in your methods that use the resource. if (!disposed) if (disposing) if (resource!= null) resource.dispose(); Console.WriteLine("Object disposed."); // Indicate that the instance has been disposed. 36 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

37 3.4 Sprachbesonderheiten resource = null; disposed = true; //Aufrufende Klasse class Program static void Main() try // Initialize a Stream resource to pass // to the DisposableResource class. Console.Write("Enter filename and its path: "); string filespec = Console.ReadLine(); FileStream fs = File.OpenRead(fileSpec); DisposableResource TestObj = new DisposableResource(fs); // Use the resource. TestObj.DoSomethingWithResource(); // Dispose the resource. TestObj.Dispose(); catch (FileNotFoundException e) Console.WriteLine(e.Message); Frage 3.17 Betrachten Sie den Pizzaservice aus EWA. In der Methode GenerateView möchten Sie HTML-Code auf Basis der in einer Datenbank hinterlegten Speisekarte ausgeben. Skizzieren Sie das Gerüst dieser Methode in C# und geben Sie an, welche Datentypen Sie verwenden würden. 3.4 Sprachbesonderheiten using Mit dem using-statement stellen Sie einen korrekten Zugri auf IDisposable-Objekte sicher. Dispose wird automatisch beim Auftreten einer Ausnahme aufgerufen. Listing 3.21: using //Using Statement using (StreamWriter sw = new StreamWriter(@"C:\MyFile.txt")) sw.write("hello, File"); 37 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

38 3.4 Sprachbesonderheiten Log/Trace Mit der Trace-Klasse lassen sich Anwendungen instrumentieren. Von einer laufenden Anwendung können Sie damit Informationsmeldungen erhalten, die beim Diagnostizieren von Problemen oder Analysieren der Leistung hilfreich sind. Trace.WriteLine("Entering Main"); Listing 3.22: Trace Mächtiger und besser zu kongurieren ist log4net Ausnahmen 4 Die Features zur Ausnahmebehandlung in C# helfen Ihnen, wenn bei der Ausführung eines Programms unerwartete oder auÿergewöhnliche Situationen auftreten. Bei der Ausnahmebehandlung wird mithilfe der Schlüsselwörter try, catch und nally versucht, Aktionen auszuführen, die möglicherweise fehlschlagen, um Fehler zu behandeln und anschlieÿend die Ressourcen zu bereinigen. Ausnahmen können von der Common Language Runtime (CLR ähnlich zur Virtual Maschine von Java), durch.net Framework oder Bibliotheken von Drittanbietern oder durch den Anwendungscode generiert werden. Ausnahmen werden mit dem throw-schlüsselwort erstellt. Es gibt jedoch im Gegensatz zu Java keine Syntax, die kennzeichnet, welche Klassen welche Ausnahmen werfen können throw wird in C# also nur zum tatsächlichen Erzeugen/werfen von Ausnahmen verwendet. In vielen Fällen wird eine Ausnahme nicht von einer Methode ausgelöst, die direkt durch den Code aufgerufen wurde, sondern von einer anderen Methode, die sich weiter unten in der Aufruiste bendet. In diesem Fall entlädt die CLR die Aufruiste, sucht eine Methode mit einem catch-block für den spezischen Ausnahmetyp und führt den ersten catch-block aus, der gefunden wird. Falls kein entsprechender catch-block in der Aufruiste gefunden wird, wird der Prozess beendet und eine Meldung für den Benutzer angezeigt. Ausnahmen sind Typen, die letztlich alle von System.Exception abgeleitet werden. Fangen Sie keine Ausnahme ab, es sei denn, Sie können sie bearbeiten, und belassen Sie die Anwendung in einem bekannten Zustand. Wenn Sie System.Exception abfangen, lösen Sie es erneut mit dem throw-schlüsselwort am Ende des catch-blocks aus. Ausnahmeobjekte enthalten ausführliche Informationen zum Fehler, z. B. den Zustand der Aufruiste und eine Textbeschreibung des Fehlers. Nicht abgefangene Ausnahmen werden von einem generischen Ausnahmehandler des Systems behandelt, der ein Dialogfeld anzeigt. Im Gegensatz zu Java, gibt es keine Checked Exceptions. Eine Checked Exception ist eine Ausnahme, bei der der Compiler prüft, ob alle Stellen, wo sie auftreten kann, durch Code zum Abfangen der Ausnahme abgedeckt sind. Der Code zum Abfangen kann dabei innerhalb derselben Methode stehen, in der die Ausnahme auftreten kann, oder auch in aufrufenden Methoden. Der Compiler wird bei Java durch das Schlüsselwort throws unterstüzt. Bei C# ist dies nicht so umgesetzt. Fängt niemand eine Exception, so bricht das Programm mit dem generischen Fehlerdialog ab. Per Design ist dies vermutlich ein Nachteil. Da jedoch viele Java-Programmierer einfach mit catch (E e) Listing 3.23: Schlechter Code Fehler schlucken Fehler schlucken, führt dies weningstens nicht zu nicht-erklärbaren Verhalten, sondern der Fehler bleibt erhalten. Frage 3.18 Was passiert bei folgendem Code? Was passiert, wenn der Pfad nicht existiert? 4 Ausnahmen und Ausnahmebehandlung 38 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

39 3.4 Sprachbesonderheiten Listing 3.24: using und Ausnahmen using (StreamWriter sw = new StreamWriter(@"C:\tmp\MyFile.txt")) sw.write("hello, File"); throw new Exception("hey"); sw.write("hello, File 2"); Console.WriteLine("done"); Indexer Indexer ermöglichen das Indizieren von Instanzen einer Klasse oder Struktur auf dieselbe Weise wie Arrays. Abgesehen davon, dass ihre Accessoren Parameter akzeptieren, sind Indexer mit Eigenschaften vergleichbar. Im folgenden Beispiel wird eine generische Klasse deniert, die mit einfachen get-accessormethoden und set- Accessormethoden ausgestattet ist. Mit diesen Methoden werden Werte zugewiesen und abgerufen. Die Program- Klasse erstellt eine Instanz dieser Klasse für das Speichern von Zeichenfolgen. class SampleCollection<T> private T[] arr = new T[100]; public T this[int i] get return arr[i]; set arr[i] = value; Listing 3.25: Indexer // This class shows how client code uses the indexer class Program static void Main(string[] args) SampleCollection<string> stringcollection = new SampleCollection<string>(); stringcollection[0] = "Hello, World"; System.Console.WriteLine(stringCollection[0]); Übersicht über Indexer Durch Indexer können Objekte auf ähnliche Weise wie Arrays indiziert werden. Ein get-accessor gibt einen Wert zurück. Ein set-accessor weist einen Wert zu. Das this-schlüsselwort wird zum Denieren der Indexer verwendet. Mithilfe des value-schlüsselworts wird der Wert deniert, der vom set-indexer zugewiesen wird. Indexer müssen nicht mit ganzzahligen Werten indiziert werden. Sie können frei wählen, wie Sie den bestimmten Suchmechanismus denieren. Indexer können überladen werden. Indexer können mehr als einen formalen Parameter haben, z. B. wenn auf ein zweidimensionales Array zugegrien wird. 39 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

40 3.5 Serialisierung Frage 3.19 Gibt es das Konzept Indexer auch in anderen Programmiersprachen? Wie ist es dort umgesetzt? 3.5 Serialisierung In.Net gibt es drei Möglichkeiten zur Serialisierung, also zur Persistierung von Objektzuständen. Wir betrachten alle drei Möglichkeiten anhand folgendem Beispiel, das sowohl öentliche als auch private Zustandsvariablen und Listen von Objekten enthält. Damit ein Objekt serialisiert werden kann, muss die Klasse mit einem Attribut als serialisierbar gekennzeichnet werden. Dies muss für jede verwendete Klasse separat geschehen im gegebenen Beispiel also für die Klasse Example und die Klasse Student. Fehlt dieses Attribut, so wird ein Laufzeitfehler geworfen. Die folgenden Listings zeigen die Serialisierungsmöglichkeiten im Überblick. ï¾using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; Listing 3.26: Serialisierung, Vorbereitung namespace CCompact [Serializable()] public class Example private int _privateint; public int PublicInt; private List<Student> _privatestudentlist; public List<Student> PublicStudentList; public Example(int i, List<String> names) _privateint = i; PublicInt = i + 1; _privatestudentlist = new List<Student>(); PublicStudentList = new List<Student>(); int j = 0; foreach (string name in names) _privatestudentlist.add(new Student(name, j++.tostring())); PublicStudentList.Add(new Student("P" + name, j++.tostring())); public override string ToString() StringBuilder sb = new StringBuilder(); sb.append("\nprivate int: "); sb.append(_privateint.tostring()); sb.append("\npublic int: "); sb.append(publicint); sb.append("\nprivate student list:\n"); foreach (Student student in _privatestudentlist) sb.append(student.tostring()); sb.append("\n"); sb.append("\npublic student list:\n"); foreach(student student in PublicStudentList) sb.append(student.tostring()); sb.append("\n"); sb.append("objekt end\n \n"); return sb.tostring(); [Serializable()] public class Student private string _name; private string _mark; public Student(string name, string mark) 40 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

41 3.5 Serialisierung _name = name; _mark = mark; public override string ToString() return _name + ":" + _mark; [Serializable()] public class ExampleSoap private int _privateint; public int PublicInt; private ArrayList _privatestudentlist; public ArrayList PublicStudentList; public ExampleSoap(int i, List<String> names) _privateint = i; PublicInt = i + 1; _privatestudentlist = new ArrayList(); PublicStudentList = new ArrayList(); int j = 0; foreach (string name in names) _privatestudentlist.add(new Student(name, j++.tostring())); PublicStudentList.Add(new Student("P" + name, j++.tostring())); public override string ToString() StringBuilder sb = new StringBuilder(); sb.append("\nprivate int: "); sb.append(_privateint.tostring()); sb.append("\npublic int: "); sb.append(publicint); sb.append("\nprivate student list:\n"); Student student; foreach (object obj in _privatestudentlist) student = obj as Student; sb.append(student.tostring()); sb.append("\n"); sb.append("\npublic student list:\n"); foreach (object obj in PublicStudentList) student = obj as Student; sb.append(student.tostring()); sb.append("\n"); sb.append("objekt end\n \n"); return sb.tostring(); public class ExampleXml private int _privateint; public int PublicInt; private List<StudentXml> _privatestudentlist; public List<StudentXml> PublicStudentList; public ExampleXml() _privatestudentlist = new List<StudentXml>(); PublicStudentList = new List<StudentXml>(); public ExampleXml(int i, List<String> names) _privateint = i; PublicInt = i + 1; _privatestudentlist = new List<StudentXml>(); PublicStudentList = new List<StudentXml>(); int j = 0; foreach (string name in names) _privatestudentlist.add(new StudentXml(name, j++.tostring())); 41 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

42 3.5 Serialisierung PublicStudentList.Add(new StudentXml("P" + name, j++.tostring())); public override string ToString() StringBuilder sb = new StringBuilder(); sb.append("\nprivate int: "); sb.append(_privateint.tostring()); sb.append("\npublic int: "); sb.append(publicint); sb.append("\nprivate student list:\n"); foreach (StudentXml student in _privatestudentlist) sb.append(student.tostring()); sb.append("\n"); sb.append("\npublic student list:\n"); foreach (StudentXml student in PublicStudentList) sb.append(student.tostring()); sb.append("\n"); sb.append("objekt end\n \n"); return sb.tostring(); public class StudentXml private string _name; public string Name get return _name; set _name = value; private string _mark; public string Mark get return _mark; set _mark = value; public StudentXml() public StudentXml(string name, string mark) _name = name; _mark = mark; public override string ToString() return _name + ":" + _mark; ï¾using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization.Formatters.Soap; using System.Xml.Serialization; using System.Xml; namespace CCompact public class SerializeExample const string FILENAME = "exampledata.dat"; public static void Run() Listing 3.27: Serialisierung 42 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

43 3.5 Serialisierung Console.Write("Using BinaryFormatter"); List<string> names = new List<string>(); names.add("asterix"); names.add("obelix"); Example exobj = new Example(42, names); Console.WriteLine("Aktuelles Objekt vor der Serialisierung:"); Console.Write(exObj.ToString()); FileStream writestream = new FileStream(FILENAME, FileMode.Create); SerializeBinary(exObj, writestream); writestream.close(); exobj = null; Console.WriteLine("set exobj = null!"); FileStream readstream = new FileStream(FILENAME, FileMode.Open); exobj = DeserializeBinary(readStream); readstream.close(); Console.Write("Objekt nach der Serialisierung und Deserialisierung:"); Console.Write(exObj.ToString()); Console.Write("\n\nUsing SOAPFormatter"); ExampleSoap exobjsoap = new ExampleSoap(42, names); Console.WriteLine("Aktuelles Objekt vor der Serialisierung:"); Console.Write(exObjSoap.ToString()); writestream = new FileStream(FILENAME, FileMode.Create); SerializeSOAP(exObjSoap, writestream); writestream.close(); exobjsoap = null; Console.WriteLine("set exobjsoap = null!"); readstream = new FileStream(FILENAME, FileMode.Open); exobjsoap = DeserializeSOAP(readStream); readstream.close(); Console.Write("Objekt nach der Serialisierung und anschliessenden Deserialisierung:"); Console.Write(exObj.ToString()); Console.Write("\n\nUsing XmlSerializer"); ExampleXml exobjxml = new ExampleXml(42, names); Console.WriteLine("Aktuelles Objekt vor der Serialisierung:"); Console.Write(exObjXml.ToString()); XmlTextWriter writer = new XmlTextWriter(FILENAME, Encoding.UTF8); SerializeXML(exObjXml, writer); writer.close(); exobjxml = null; Console.WriteLine("set exobjxml = null!"); XmlTextReader reader = new XmlTextReader(FILENAME); exobjxml = DeserializeXML(reader); reader.close(); Console.Write("Objekt nach der Serialisierung und anschliessenden Deserialisierung:"); Console.Write(exObjXml.ToString()); Console.ReadLine(); private static void SerializeBinary(Example exobj, FileStream stream) BinaryFormatter serializer = new BinaryFormatter(); serializer.serialize(stream, exobj); private static Example DeserializeBinary(FileStream stream) BinaryFormatter serializer = new BinaryFormatter(); Example exobj = serializer.deserialize(stream) as Example; return exobj; private static void SerializeXML(ExampleXml exobj, XmlTextWriter writer) XmlSerializer serializer = new XmlSerializer(typeof(ExampleXml)); serializer.serialize(writer, exobj); private static ExampleXml DeserializeXML(XmlTextReader reader) XmlSerializer serializer = new XmlSerializer(typeof(ExampleXml)); ExampleXml exobj = serializer.deserialize(reader) as ExampleXml; return exobj; private static void SerializeSOAP(ExampleSoap exobj, FileStream stream) 43 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

44 3.5 Serialisierung SoapFormatter serializer = new SoapFormatter(); serializer.serialize(stream, exobj); stream.close(); private static ExampleSoap DeserializeSOAP(FileStream stream) SoapFormatter serializer = new SoapFormatter(); ExampleSoap exobj = serializer.deserialize(stream) as ExampleSoap; return exobj; BinaryFormatter Der BinaryFormatter benötigt einen Stream und das zu serialisierende Objekt. SoapFormatter Für diese Serialisierung müssen Sie zunächst die Referenz auf System.Runtime.Serialization.Formatters.Soap.dll hinzufügen. Leider unterstützt der SOAP-Formatter keine generischen Typen, die Studentenliste kann so also nicht serialisiert werden. Ersetzt man jedoch den generischen Typ durch beispielsweise eine ArrayList, dann funktioniert es wieder problemlos. Die erzeugte Datei enthält korrektes SOAP. Durch Implementation der Schnittstelle ISerializable lässt sich das erzeugte SOAP auch weiter kongurieren. Merke 5 (Serialisierung mit SOAP) Der SoapFormatter kann generische Typen nicht serialisieren. XMLSerializer XML-Serialisierung ist gut für den Austausch von Daten mit anderen Applikationen. Leider sind an die XML-Serialisierung weitere Nebenbedingungen geknüpft. Zunächst wird ein leerer Konstruktor benötigt dies gilt natürlich auch für die verwendete Student-Klasse. Das Attribut Serializable wird dagegen nicht mehr benötigt. Initialisiert der leere Konstruktor auch den privaten Member mit einer leeren Liste, dann funktionieren Serialisierung und Deserialisierung: Ein Blick auf die deserialisierten Daten und das XML oenbart jedoch: Es werden standardmäÿig nur die öentlichen Werttypen serialisiert. Der private int-wert ist also nicht persistent abgelegt, ebenso wenig wie die Studentenobjekte. Wir refactorn die Student-Klasse und extrahieren die Felder zu den privaten Membern. In der Beispielklasse verzichten wir nun auf die privaten Member, da sie nur Demonstrationszwecken dienten. Nun funktioniert die Serialisierung und Deserialisierung. Mit entsprechenden Attributen kann man das erzeugte XML auch denieren, siehe Steuern der XML-Serialisierung mit Attributen. Anmerkung: Während der SOAP-Formatter generische Listen nicht serialisieren kann und die Alternative ArrayList funktionierte, kann der XML-Serialisierer mit ArrayList nichts anfangen. Merke 6 (Serialisierung mit XML) Der XmlSerializer benötigt einen leeren Konstruktor und kann keine privaten Member serialisieren. 44 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

45 3.6 P2 - C# kompakt 3.6 P2 - C# kompakt Abgabetermin: Merke 7 (Option Code Analysis) Aktivieren Sie von nun an für alle Projekte und abzugebenen Praktikumsaufgen Enable Code Analysis on Build mit Microsoft all rules, XML-Dokumentation und setzen Sie sich mit den Coding Guidelines auseinander. Abbildung 3.5: MP3-Player, schlechter Entwurf Aufgabe P2.1 Diskutieren Sie den in Abbildung 3.5 abgebildeten Entwurf in Bezug auf: (a) Funktionalität: Lassen sich mit diesem Entwurf die gewünschten Anforderungen umsetzen? Wenn nein, was fehlt? Vervollständigen Sie den Entwurf ggf. (b) Namenskonvention: Sind die Klassen, Interfaces und Methoden einheitlich, z.b. nach den Microsoft Guidelines, benannt? Korrigieren Sie ggf. (c) OO-Prinzipien: Benennen Sie drei wichtige OO-Prinzipien (wie z.b. Komposition vor Vererbung) und untersuchen Sie den Entwurf daraufhin. Welche Verbesserungen schlagen Sie vor? (d) Erweiterbarkeit: In Zukunft soll es auch möglich sein, Videos abzuspielen. Es wird auch über eine Web- Anzeige oder eine Windows7-App nachgedacht. Ist dies mit diesem Entwurf möglich? Nennen Sie weitere mögliche Erweiterungen und diskutieren Sie die Möglichkeiten anhand des gegebenen Entwurfs. (e) Automatische Tests: Welche Teile lassen sich automatisch testen? Entwickeln Sie geeignete Testfälle. Aufgabe P2.2 Implementieren Sie das Grundgerüst Ihres Audio-Players inklusive automatischer Tests. Auf die Methoden Play, Stop etc. müssen Sie noch nicht eingehen. 45 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

46 3.7 Delegates (a) Implementieren Sie Methoden zum Hinzufügen und Entfernen von Playlists. (b) Implementieren Sie Methoden zum Hinzufügen und Entfernen von Elementen einer Playlist. (c) Implementieren Sie Methoden zum Serialisieren und Deserialisieren einer Playlist. Aufgabe P2.3 Implementieren Sie eine Basisklasse, die ein einfaches Interface implementiert. Erstellen Sie weitere zwei abgeleitete Klassen. Die Klassen sollen private Member, Methoden und öentliche Properties und Methoden sowie einen Indexer enthalten. Verwenden Sie optionale Parameter und Methodenüberladung. Verwenden Sie generische Listen. (a) Serialisieren Sie auf drei verschiedene Arten. (b) Deserialisieren Sie auf drei verschiedene Arten. (c) Vewenden Sie beim XMLSerializer geeignete Attribute. Lesen Sie diese an anderer Stelle aus und geben Sie sie auf der Console aus. Aufgabe P2.4 Erläutern Sie den Unterschied von Exceptions in.net im Vergleich zu PHP oder Java. Aufgabe P2.5 Implementieren Sie einen Struct Bruch zum Rechnen mit Brüchen. Implementieren Sie mittels Operator- Overloading die Addition, Multiplikation und den Vergleich von Brüchen. 3.7 Delegates Ein Delegate ist ein Objekt, welches auf eine Methode zeigt, die zu einem späteren Zeitpunkt aufgerufen werden kann. Für C++ Programmierer sind Delegate typsichere Funktionszeiger. Für andere einfach ein Datentyp, der Methoden aufnehmen kann. Dies ist für Python- Entwicklerinnen oder Anhängern der funktionale Programmierung keine Besonderheit. Für.Net sind Delegates die Basis des Eventhandlings und für asynchrone Programme. Wie wird ein Delegat deniert? Betrachten wir folgendes Beispiel: 1 delegate double MathDelegate(double angle); 2 MathDelegate calculator; 3 calculator = Math.Sin //oder auch = new MathDelegate(Math.Sin) 4 System.Diagnostics.Debug.WriteLine(calculator(45)) Zeile 1 deniert einen bestimmten Delegattyp (MathDelegate), Zeile 2 deklariert eine Delegatvariable (calculator) und Zeile 3 instanziiert sie mit einer statischen Methode. Die Delegatvariable wird nun wie die Methode die sie enthält verwendet (Zeile 4). Was passiert dabei im Hintergrund? In.Net sind alles Objekte, von welcher Klasse ist also calculator eine Instanz? Durch das Schlüsselwort delegate in Zeile 1 wird eine neue Klasse erzeugt, die von der Basisklasse System.MulticastDelegate abgeleitet wird. Zeile 1 deniert dabei auch genau, welche Art von Funktionen aufgenommen werden können, nämlich nur die Methoden, die der angegebenen Signatur folgen, also ein double als Argument erwarten und ein double zurückgeben. Auf Multicast-Delegates, die wir also eigentlich immer erhalten, werden wir in Abschnitt auf Seite 49 genauer eingehen. Wichtig ist hierbei: Da wir von dieser Klasse erben, erben wir auch alle Methoden, Eigenschaften und Operatoren. Es lohnt sich also, die Referenz zu konsultieren: MulticastDelegate Class. Im obigen Beispiel wurde eine statische Methode, also eine zustandslose Methode, verwendet. Delegates können aber auch Objektmethoden aufnehmen: public class Discounter private string name; public Discounter(string name) this.name = name; public string GetGreeting() return "Hi " + this.name; 46 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

47 3.7 Delegates public class Shop delegate string GreetingDelegate(); public void Test() Discounter disc = new Discounter("donald"); greet = disc.getgreeting System.Diagnostics.Debug.WriteLine(greet()) Generell ist zu beachten, dass private Methoden auch für Delegate privat bleiben, d.h. auch ein Delegat kann nicht auf eine private Methode einer anderen Klasse zugreifen. Abstrakte Methoden können nicht aufgenommen werden, es muss immer eine konkrete Implementation existieren. Virtual deklarierte Methoden, sind dagegen kein Problem. Bezüglich der denierten Signatur eines Delegattypen ist wichtig, dass die aufzunehmenden Methoden nicht wirklich identische Signaturen aufweisen müssen, sondern abgeleitete Klassen bzgl. des Rückgabewertes und Basisklassen bzgl. der Argumente auch zulässig sind: public delegate Employee HandlerMethod(Manager man); HandlerMethod worker; worker = FirstHandler; public static Manager FirstHandler(Employee worker) public class Manager : Employee Die Signatur der aufzunehmenden Methode darf abweichen: Der Rückgabewert muss vom vorgegebenen oder einem davon abgeleiteten Objekttyp sein, d.h. das Delegat deniert Employee als geforderten Rückgabewert und akzeptiert alle Methoden, die Employee oder von Employee abgeleitete Klassen zurückgeben. Dies läuft unter dem Begri Covariance. Die Argumente müssen vom vorgegebenen oder einem dazugehörigen Basistyp sein, d.h. das Delegat deniert Manager als gefordertes Argument und akzeptiert alle Methoden, die Manager oder einen Basistyp von Manager als Argument erwarten. Dies läuft unter dem Begri Contravariance. Wird eine Funktion/Methode nur für ein Delegat benötigt, dann kann diese auch direkt als anonyme Funktion dem Delegat übergeben werden: delegate void TestDelegate(string s); TestDelegate testdelb = delegate(string s) Console.WriteLine(s); ; Manche sprechen hierbei auch von anonymen Delegaten, wobei ich dies eher irreführend nde. Neben der hier dargestellten Schreibweise gibt es eine weitere, noch kürzere Darstellung, die sich Lambda-Ausdruck nennt, auf die wir in Abschnitt?? auf Seite?? noch einmal eingehen werden: delegate void TestDelegate(string s); TestDelegate testdelc = (x) => Console.WriteLine(x); ; Delegates werden sehr häug für Sortierfunktionen verwendet, wie folgendes Beispiel von Stackoverow.com zeigt: public string SortByDateModified(List<CartItem> items) items.sort(delegate(cartitem itema, CarItem itemb) return itema.datemodified.compareto(itemb.datemodified); ); 47 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

48 3.7 Delegates Wann können Delegate eingesetzt werden? Immer dann, wenn mehr als eine konkrete Implementation einer Methode relevant ist. Delegate sind somit auf Methodenebene mit Schnittstellen (Interfaces) auf Klassenebene vergleichbar. Sie können auch immer dann verwendet werden, wenn über ein Interface mit nur einer Methode nachgedacht wird. Sie können zur Umsetzung folgender Entwurfsmuster verwendet werden: Adapter, Command, Mediator, Chain, Observer, Visitor. Seit 2005 sind Delegate laut Microsoft genauso performant wie Schnittstellen (Interfaces). Delegate sind natürlich Referenztypen, die auf dem Heap liegen. Frage 3.20 Finden Sie drei weitere Anwendungsbeispiele für Delegates. Ein Delegat kann entweder (wie in diesem Beispiel) synchron oder mithilfe der BeginInvoke-Methode und der EndInvoke-Methode asynchron aufgerufen werden Generische Delegates In.Net gibt es generische Listen, Methoden, Klassen, Schnittstellen und auch generische Delegate. public delegate void Del<T>(T item); public static void Notify(int i) Del<int> m1 = new Del<int>(Notify); Zeile 1 deniert ein generisches Delegat. Erst bei der Instanzierung in Zeile 3 wird der Typ festgelegt. Durch die Einführung von generischen Delegattypen im Namensraum System (ab.net 2.0) werden eigene Delegatdenitionen (weitestgehend) überüssig: public delegate TResult Func<in T, out TResult>(T arg) public delegate void Action<in T>(T obj) Func ist also der Delegattyp zur Aufnahme von Methoden mit Rückgabewert und Action für Methoden ohne Rückgabewert. Ab.Net 4.0 gibt es beide Delegate mit bis zu 10 Argumenten. Damit sollte sich jeder Delegattyp denieren lassen (von.net-attributen abgesehen). Es gibt auch vordenierte generische Delegate, die bereits mit geeigneten Attributen versehen sind, wie z.b. AppDomainInitializer-Delegat. Oder für den häugen Anwendungsbereich Sortieren mit Delegaten, gibt es Comparison<T>-Delegat. Zur Veranschaulichung, betrachte ich ein Beispiel aus dem empfehlendswerten Buch Kompaktkurs C# 4.0, wie mit Hilfe des Func-Delegats auf der Konsole eine mathematische Funktion geplottet werden kann. Anstelle der eigenen Denition delegate double Function(double x); Verwenden wir Func<double, double> Hier das vollständige Programm, das einmal einen Lambda-Ausdruck (Zeile 6) an die Funktion Plot übergibt und einmal eine statische Funktion (Zeile 8). 48 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

49 3.7 Delegates class Program static void Main(string[] args) Console.WriteLine("Linear:"); Plot(x => x); Console.WriteLine("\nParabel:"); Plot(Parabel); Console.ReadLine(); static double Parabel(double x)return x*x; static void Plot(Func<double, double> f) // create a 50 x 50 drawing plane char[,] dot = new char[50, 50]; for (int i = 0; i < dot.getlength(0); i++) for (int j = 0; j < dot.getlength(1); j++) dot[i, j] = ' '; // compute the function int height = dot.getlength(0); for (int x = 0; x < dot.getlength(1); x++) int y = (int)f(x); if (0 <= y && y < height) dot[(height - 1) - y, x] = '*'; // draw the plot for (int i = 0; i < dot.getlength(0); i++) Console.Write(' '); for (int j = 0; j < dot.getlength(1); j++) Console.Write(dot[i, j]); Console.WriteLine(); for (int i = 0; i < dot.getlength(1); i++) Console.Write('-'); Frage 3.21 Decken die vordenierten Delegates alle Anwendungsfälle für Delegates ab, d.h. ist es nicht mehr notwendig eigene Delegates zu denieren? Wie zu erwarten, gilt auch für generische Delegate die Aussage bzgl. Kontravarianz und Kovarianz, wie im ersten Teil bereits dargestellt. Generische Delegate sind ja eigentlich nichts Besonderes, schlieÿlich werden bei der Deklaration der Delegatvariablen konkrete Datentypen angegeben. Die Kombination von Kovarianz und Kontravarianz veranschaulicht folgendes Codefragment, das ich von Microsoft übernommen habe. public class Base public class Derived : Base public static Derived MyMethod(Base b) return b as Derived?? new Derived(); // Covariant return type and contravariant parameter type. Func<Derived, Base> f = MyMethod; Base b = f(new Derived()); Frage 3.22 Was liefert folgender Code und warum? var contents = new List<Func<int>>(); var s = new StringBuilder(); for (var i = 4; i < 7; i++) contents.add(() => i); 49 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

50 3.7 Delegates for (var k = 0; k < contents.count; k++) s.append(contents[k]()); Console.WriteLine(s); Was ist hier anders? var contents = new List<Func<int>>(); var s = new StringBuilder(); for (var i = 4; i < 7; i++) var j = i; contents.add(() => j); for (var k = 0; k < contents.count; k++) s.append(contents[k]()); Console.WriteLine(s); Mulitcastdelegaten Eine nützliche Eigenschaft von delegate-objekten besteht darin, dass sie mithilfe des Operators + einer Delegatinstanz als Multicast zugewiesen werden können. Ein zusammengesetzter Delegat ruft die beiden Delegaten auf, aus denen er besteht. Es können ausschlieÿlich Delegaten mit demselben Typ kombiniert werden. Mithilfe des Operators - kann ein Komponentendelegat aus einem zusammengesetzten Delegaten entfernt werden. Das folgende Beispiel zeigt die Verwendung dieser Operatoren. delegate void Del(string s); class TestClass static void Hello(string s) System.Console.WriteLine(" Hello, 0!", s); static void Goodbye(string s) System.Console.WriteLine(" Goodbye, 0!", s); static void Main() Del a, b, c, d; a = Hello; b = Goodbye; c = a + b; d = c - a; Listing 3.28: Multicastdelegaten System.Console.WriteLine("Invoking delegate a:"); a("a"); System.Console.WriteLine("Invoking delegate b:"); b("b"); System.Console.WriteLine("Invoking delegate c:"); c("c"); System.Console.WriteLine("Invoking delegate d:"); d("d"); Frage 3.23 Was gibt das Programm Multicastdelegaten aus? 50 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

51 3.7 Delegates Ereignisse Delegate sind in.net die Basis für Events (Ereignisse). Events sind die Technologie, wie verschiedene Komponenten eines Programms und insbesondere einer GUI miteinander kommunizieren. Klickt ein Anwender auf einen Knopf, so ändert sich der Zustand dieses Knopfes (er ist gedrückt) und alle, die sich dafür interessieren werden darüber informiert alle Zuhörer (Listener) können entsprechend reagieren. Z.B. kann nun ein Datensatz in die Datenbank geschrieben werden. Java bildet dies in entsprechenden Klassen ab..net tut dies versteckt mit besonderen Delegaten. Warum ich hier versteckt schreibe hat den Grund, dass normale Delegatvariablen nach auÿen hin zu sichtbar sind. Dies soll folgender Abschnitt erläutern. Ereignisse mit normalen Delegatvariablen: Gefährliches Lotto Betrachten wir zunächst die Möglichkeit, Ereignisse mit Delegatvariablen umzusetzen..net bietet uns eine für Ereignisse nützliche Delegatdenition: public delegate void EventHandler (Object sender,eventargs e) Und als generische Version, mit eigenen Argumenten: public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e); In einer Klasse soll eine Zustandsänderung (die Ziehung neuer Lottozahlen) per Delegat allen Interessenten mitgeteilt werden, also z.b. public class Lotto public EventHandler<LottoEventArgs> LottoAmMittwoch; public void Ziehung() if (LottoAmMittwoch!= null) LottoAmMittwoch(this, new LottoEventArgs(new List<int> 8, 4, 36, 1, 28, 2 )); public class LottoEventArgs: EventArgs public LottoEventArgs(List<int> ziehung) if (ziehung.count!= 6) throw new ArgumentException("needs exactly 6 integers", "ziehung"); this.ziehung = ziehung; public List<int> Ziehung; Ein Kiosk kann zwei Spieler anmelden: public class Spieler public string Name; public List<int> Tipp; public Spieler(string name, List<int> tipp) this.name = name; this.tipp = tipp; public void Auswerten(Object sender, LottoEventArgs eargs) int countwon = 0; for (int i=0;i<tipp.count;i++) if (eargs.ziehung.contains(tipp[i])) countwon++; Console.WriteLine(string.Format("0 hat 1:d Richtige", Name, countwon)); public class Kiosk Lotto lotto; public Kiosk(Lotto lotto) this.lotto = lotto; 51 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

52 3.7 Delegates public void Anmeldungen() Spieler gierigerspieler = new Spieler("Dagobert", new List<int> 1, 2, 3, 4, 5, 6 ); lotto.lottoammittwoch += gierigerspieler.auswerten; Spieler normalerspieler = new Spieler("Otto", new List<int> 2, 4, 6, 8, 10, 12 ); lotto.lottoammittwoch += normalerspieler.auswerten; Und das Programm nimmt die Anmeldungen entgegen und führt die Ziehung durch: Lotto lotto = new Lotto(); Kiosk kiosk1 = new Kiosk(lotto); kiosk1.anmeldungen(); lotto.ziehung(); Dies führt zur Ausgabe: Dagobert hat 3 Richtige Otto hat 3 Richtige Bei öentlichen Delegaten, wie hier verwendet und zur Anmeldung durch den Kiosk benötigt, kann der Kioskbesitzer aber auch mit Dagobert gemeinsame Sache machen und folgende Zeilen einfügen: //Ziehung manipulieren lotto.lottoammittwoch = gierigerspieler.auswerten; lotto.lottoammittwoch(lotto, new LottoEventArgs(gierigerSpieler.Tipp)); Damit wird nur die Auswertung von Dagobert aufgerufen (alle weiteren bis dahin registrierten Methoden werden durch diese eine Methode überschrieben) und LottoAmMittwoch wird mit den Zahlen von Dagobert aufgerufen. Dies führt zur Ausgabe: Dagobert hat 6 Richtige Dagobert hat 3 Richtige Die erste Zeile erfolgt aus der Manipulation, dass LottoAmMittwoch direkt aufgerufen wird und die zweite Zeile resultiert aus dem Aufruf lotto.ziehung() im eigentlichen Programm. Wir stehen also vor dem Problem, dass es einerseits von auÿen möglich sein soll, sich zu registrieren und zu deregistrieren. Auf der anderen Seite soll es aber nicht möglich sein, die Registrierung von anderen zu überschreiben oder das Ereignis selbst auszulösen. Man kann dies selbst programmieren, in dem man Methoden Subscribe und Unsubscribe öentlich macht und das Delegat selbst privat oder dieses Pattern.Net überlässt und das Schlüsselwort event verwendet. Diese Möglichkeit zeigt der nächste Abschnitt. Delegatvariablen und das Schlüsselwort event public class Lotto public event EventHandler<LottoEventArgs> LottoAmMittwoch; Damit ist ein Registrieren und Deregistrieren weiter möglich, aber der Betrugsversuch nicht mehr. IL-Disassembler zeigt uns, was in beiden Fällen erzeugt wird. Für die Delegat- Events mit IL-Disassembler variable, erhalten wir:.field public class [mscorlib]system.eventhandler`1<class GenericDelegate.LottoEventArgs> LottoAmMittwoch Während die Event-Deklaration dies erzeugt:.event class [mscorlib]system.eventhandler`1<class GenericDelegate.LottoEventArgs> LottoAmMittwoch.addon instance void GenericDelegate.Lotto::add_LottoAmMittwoch(class [mscorlib]system.eventhandler`1<class GenericDelegate.LottoEventArgs>).removeon instance void GenericDelegate.Lotto::remove_LottoAmMittwoch(class [mscorlib]system.eventhandler`1< class GenericDelegate.LottoEventArgs>) 52 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

53 3.7 Delegates Leider hat hier die GUI von IL-Disassembler schon wieder das Schlüsselwort event reingeschmuggelt, denn begibt man sich auf die Kommandozeile mit: ildasm "TestDelegate.exe" /out= TestDelegate.il Dann erhält man:.field private class [mscorlib]system.eventhandler`1<class GenericDelegate.LottoEventArgs> LottoAmMittwoch.method public hidebysig specialname instance void add_lottoammittwoch(class [mscorlib]system.eventhandler`1<class GenericDelegate.LottoEventArgs> 'value') cil managed Also eigentlich wird auch hier ein eld erzeugt, aber erstens ist dies private und nicht public wie oben und zweitens werden öentliche Methoden zum Registrieren und Deregistrieren erzeugt. Genau das Pattern, was wir am Ende des letzten Abschnitts vorgeschlagen haben. Ein typisches Event-Beispiel Die bisherigen Ausführungen dienten dazu, den Unterschied zwischen einer als event deklarierten Variablen und einer gewöhnlichen Delegatvariablen herauszuarbeiten. Abschlieÿend betrachten wir noch ein typisches Beispiel aus der GUI-Programmierung. Wenn Sie beispielsweise einen Button auf die Oberäche ziehen und diesen Doppelklicken, dann wird sichtbar folgender Code erzeugt: private void button1_click(object sender, EventArgs e) //Ereignisroutine für das Drücken des Buttons Im Hintergrund wird zusätzlich folgender Code erzeugt: this.button1.click += new System.EventHandler(this.button1_Click); was man auch kürzer als this.button1.click += this.button1_click; schreiben könnte. Die Methode button1_click wird also registriert. Markiert man Click und drückt F12, erscheint die zugehörige Denition: public class Control public event EventHandler Click; protected virtual void OnClick(EventArgs e); Wobei Button von ButtonBase und diese wiederum von Control erbt. Innerhalb einer Klasse (hier Button bzw. Control) wird also ein event deniert (hier Click) und für dieses Ereignis einer entsprechenden Instanz dieser Klasse (hier button1), kann eine Methode registriert werden (hier button1_click). Die zugehörige Namenskonvention lässt sich auch sehr schön ableiten. CustomControl Submit Im Allgemeinen haben wir also eine Klasse, die ein Event (MyEvent) mit eigenen Argumenten (MyEventArgs siehe Denition von LottoEventArgs) deniert: public class MyEventArgs : EventArgs class MyGUIElement : Control public event EventHandler<MyEventArgs> MyEvent; protected virtual void OnMyEvent(MyEventArgs myevent) if (MyEvent!= null) MyEvent(this, myevent); // Notify Subscribers public void PerformMyEvent() //possible validation OnMyEvent(new MyEventArgs()); 53 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

54 3.7 Delegates Wir erzeugen eine Instanz dieser Klasse: private MyGUIElement myguielement; myguielement = new MyGUIElement(); Und registrieren eine entsprechend denierte Methode: myguielement.myevent += myguielement_myevent; private void myguielement_myevent(object sender, EventArgs e) MessageBox.Show("myevent was raised"); Jetzt muss dieses Ereignis durch irgendetwas ausgelöst werden, z.b. durch ein Klick, also muss für Click eine Methode registriert werden, die MyEvent auslöst: myguielement.click += myguielement_click; private void myguielement_click(object sender, EventArgs e) //raise submit myguielement.performmyevent(); Anschaulicher wird dies im konkreten Fall eines CustomControls. Der Code basiert auf einem Artikel von arcadia. public class SubmitButtonControl : System.Windows.Forms.UserControl private System.Windows.Forms.TextBox txtname; private System.Windows.Forms.Button btnsubmit;... //use predened delegate Action public event Action Submit; protected virtual void OnSubmit() if (Submit!= null) Submit(); // Notify Subscribers private void btnsubmit_click(object sender, System.EventArgs e) if (txtname.text.length == 0) //noch schöner mit ErrorProvider! MessageBox.Show("Please enter your name."); else //submit Ereignis auslösen OnSubmit(); public string UserName get return txtname.text; set txtname.text = value; Frage 3.24 Beschreiben Sie die Konzepte delegate und event und das Zusammenspiel sowie mögliche Gemeinsamkeiten und Unterschiede. 54 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

55 3.7 Delegates Asynchrone Delegates Asynchrone Programmierung ist ein schwer abzugrenzendes Thema. In Bezug auf Delegates fangen wir mit einem einfachen Beispiel an: Während im Hintergrund beispielsweise die Festplatte durchsucht wird, läuft das Hauptprogramm weiter. An einer fest gelegten Stelle im Hauptprogramm wird das Ergebnis der Suche verarbeitet. Entweder die Suche ist dann schon abgeschlossen, oder das Programm wartet nun, bis dies geschehen ist (Zeile 32). Wir denieren also wieder ein Delegate (Zeile 1), instanziieren es mit einer der Signatur entsprechenden Methode (Zeile 24) und mit BeginInvoke (Zeile 25) leiten wir den asynchronen Aufruf ein. Mit EndInvoke (Zeile 32) warten wir auf sein Ende. Danach können wir den Rückgabewert (die Liste der gefundenen Dateien) verarbeiten. delegate List LongProcessCaller(string name); public class Test public List Search(string path) List result = new List(); Console.WriteLine("async: start long search process in " + path); for (int i = 0; i < 2; i++) System.Threading.Thread.Sleep(50); result.add("filename " + i.tostring()); Console.WriteLine("async: found one file"); Console.WriteLine("async: finnished long search process..."); return result; class Program static void Main(string[] args) Test t = new Test(); Console.WriteLine("Hello this is the main program,..."); LongProcessCaller caller = new LongProcessCaller(t.Search); IAsyncResult result = caller.begininvoke(@"c:\tmp", null, null); for (int i = 0; i < 3; i++) Console.WriteLine("main:I work too..."); System.Threading.Thread.Sleep(25); Console.WriteLine("main: wait for long process to finnish"); List found = caller.endinvoke(result); Console.WriteLine("main:found the following items: "); foreach (string filename in found) Console.WriteLine(filename); Console.ReadLine(); Jetzt wartet das Programm zwar nicht direkt beim Aufruf der Routine, aber doch ggf. später. Schöner wäre es, wenn die Verarbeitung des Ergebnisses der Suche dann erfolgen könnte, wenn die Suche beendet ist. Dies ist durch Übergabe einer Methode bei BeginInvoke (Zeile 26) möglich: 55 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

56 3.7 Delegates 1 // restlicher Code wie oben 2 IAsyncResult result = caller.begininvoke(@"c:\tmp", new AsyncCallback(MyCallback), null); 3 //... EndInvoke nicht hier! 4 static void MyCallback(IAsyncResult async) 5 6 System.Runtime.Remoting.Messaging.AsyncResult ar = (System.Runtime.Remoting.Messaging.AsyncResult) async; 7 LongProcessCaller caller = (LongProcessCaller)ar.AsyncDelegate; 8 List found = caller.endinvoke(async); 9 Console.WriteLine("callback:found the following items: "); 10 foreach (string filename in found) 11 Console.WriteLine(filename); 12 Um an das eigentliche Ergebnis zu kommen, muss man trickreich casten, aber die Codezeilen lassen sich leicht auf andere Probleme übertragen. Auf diese Art und Weise lieÿen sich viele Hintergrundarbeiten gleichzeitig starten: for (int i = 0; i < 50; i++) IAsyncResult result = caller.begininvoke(i.tostring(), new AsyncCallback(MyCallback), null); Mit BeginInvoke wird ein Thread im ThreadPool gestartet. Die Anzahl der möglichen Threads im Threadpool ist beschränkt, ggf. landet ein Thread dann in der Warteschlange. Dies ist nur ein sehr kurzer Einstieg in die asynchrone Programmierung und ich beschränke mich in dieser Stelle auch nur auf die einfache und direkte Möglichkeit, die Delegate bieten. Mit der neuen.net-sprache F# oder den Task-Klassen bieten sich viel mehr Möglichkeiten. Mehr zu asynchroner oder paralleler Programmierung (hier tut sich gerade im.net-umfeld sehr viel) nden Sie hier: Threading in C# Parallel Programming with Microsoft.NET Multithreading, Delegates, and Custom Events (mit UI) Scalable Multithreaded Programming with Tasks LINQ In einem datenbankbasierten Projekt mussten wir häug kompliziertere Abfragen zusammen bauen. Egal, in welcher Programmiersprache, läuft dies normalerweise darauf hinaus, sich entsprechend parametrisierte Strings zusammen zu setzen. Schnell vergisst man eine Klammer, schlieÿt den String nicht oder macht andere Syntaxfehler. Ein automatischer Test zeigt diese zwar direkt auf, aber die Entwicklung ist umständlich, die Fehler schwer zu nden. Mit LINQ (language integrated query) bietet.net eine an SQL angelehnte Abfragesprache, mit Syntax-Check durch den Compiler. Folgendes Beispiel zeigt eine einfache LINQ-Abfrage: //Code 1 List members = new List(); members.add(new Member(30, "Tim")); members.add(new Member(5, "Struppi")); members.add(new Member(53, "Kapität Haddock")); members.add(new Member(60, "Prof. Bienlein")); IEnumerable oldies = from m in members where m.age > 50 select m.name; foreach(string name in oldies) Console.WriteLine(name); 56 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

57 3.7 Delegates Erweiterungsmethoden Mit Hilfe des ObjektBrowsers können Sie sich leicht die Denition für where ansehen (F12 funktioniert leider nicht): //Namespace System.Linq.Enumerable public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate ); Erweiterungsmethoden wurden mit.net 3.5 eingeführt. Mit ihnen kann von auÿen, sozusagen im Nachhinein Funktionalität zu vorhandenen Klassen hinzugefügt werden. Func ist ein vordeniertes Delegate. Noch mehr Hintergrundinformation erhält man mit dem Reector und Disassembling: //Code 2 IEnumerable oldies = members.where(delegate (Member m) return (m.age > 50); ).Select(delegate (Member m) return m.name; ); Mit Lambda lieÿe sich dies auch umschreiben in: //Code 3 IEnumerable oldies = members.where(m => m.age > 50).Select(m => m.name); Disassembling liefert hier, wie nicht anders zu erwarten, das in Code 2 aufgeführte Ergebnis. In dieser Schreibweise funktioniert auch ein F12 auf dem markierten Where. Merke 8 (LINQ) Das Ergebnis einer LINQ-Abfrage ist keine Liste, sondern IEnumerable auf Basis eines Delegates Abfragen Unter 101 LINQ Samples nden Sie viele weitere unterschiedliche LINQ-Beispiele. Die Schlüsselwörter und Möglichkeiten sind mit SQL vergleichbar. Hier ist eine kleine Auswahl dieser Beispiele: Listing 3.29: LINQ-Beispiele //Select Beispiel int[] numbers = 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ; string[] strings = "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" ; var textnums = from n in numbers select strings[n]; //Count Beispiel int[] factorsof300 = 2, 2, 3, 5, 5 ; int uniquefactors = factorsof300.distinct().count(); Console.WriteLine("There are 0 unique factors of 300.", uniquefactors); //Order Beispiel double[] doubles = 1.7, 2.3, 1.9, 4.1, 2.9 ; var sorteddoubles = from d in doubles orderby d descending select d; var doublesarray = sorteddoubles.toarray(); //Join Beispiel string[] categories = new string[]"beverages", "Condiments", "Vegetables", "Dairy Products"; List<Product> products = GetProductList(); var q = from c in categories join p in products on c equals p.category into ps select new Category = c, Products = ps ; 57 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

58 3.7 Delegates Frage 3.25 Welche zugrundeliegende Struktur können Sie bei den aufgeführten Beispielen entdecken? In den oben aufgeführten Beispielen wird der LINQ-Ausdruck immer dem implizit typisierten Typ var zugeordnet. Var ist ein Typ, der dem Compiler sagt, den dafür passenden Typ einzusetzen, der eigentliche Typ wird also zur Compile-Zeit festgelegt, nicht zur Laufzeit. Der tatsächliche Typ ist, wie in Abschnitt auf Seite 55 eingeführt IEnumerable<TSource>. Übergeben wird ein Delegate, also ein Methodenzeiger. Das Ergebnis einer LINQ-Abfrage ist also nicht, wie vielleicht zu erwarten, eine Liste oder ähnliches, sondern ein dynamischer Ausdruck, der erst bei Zugri auf ein konkretes Element, wie beim Durchlaufen einer foreach-schleife oder der Methode ToList ausgewertet wird! Betrachten Sie hierzu folgendes Beispiel: int[] data=1,2,3,1,2,1; var list = new List<IEnumerable<int>>(); foreach (var in in data.distinct()) list.add(from k in data where k==i select k); foreach (var m in list) foreach (var n in m) Console.Write(n); Listing 3.30: LINQ-Falle Frage 3.26 Was wird hier ausgegeben und warum? Welche Parallele sehen Sie zu Frage 3.22? (1) (2) 123 (3) 333 (4) keine der genannten 58 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

59 3.8 P3* - Delegates und Events 3.8 P3* - Delegates und Events Abgabetermin: Aufgabe P3.1 Ziel des heutigen Praktikums ist es, den nicht GUI-basierten Teil der Playlist zu implementieren. (a) Implementieren Sie geeignete Sortiermethoden mit Hilfe von Delegates. (b) Schreiben Sie die Sortiermethoden unter Verwendung von anonyme Methoden. (c) Implementieren Sie alle weiteren nicht GUI-basierten Methoden. (d) Erzeugen Sie ein Klassendiagramm Ihrer Applikation. (e) Erzeugen Sie ein Sequenz-Diagramm. Aufgabe P3.2 Erläutern Sie folgenden Code. Legen Sie eine Wertetabelle mit n = 1,2,3 und xxx an. Was wird hier berechnet? Func<int, int> xxx = null; xxx = (n) => n <= 1? 1 : n + xxx(n - 1); Aufgabe P3.3 Erstellen Sie eine Liste von Personen mit den Eigenschaften Name und Alter. Erstellen Sie dazugehörige LINQ- Ausdrücke, die (a) Den Namen aller Personen unter 18 anzeigt. (b) Ein Array mit allen Personen über 18 erzeugt. Aufgabe P3.4 Wählen Sie ein Pattern, das in http: // www. cs. dartmouth. edu/ ~sensorlab/ pubs/ SL-HotEmnets08. pdf dargestellt wird. (a) Beschreiben Sie kurz den Zweck des Patterns anhand eines geeigneten Beispiels. (b) Implementieren Sie dieses Pattern in einer Nicht-.Net-Programmiersprache Ihrer Wahl. (c) Diskutieren Sie die Unterschiede der Implementation der Teilaufgabe (b) mit der im Paper dargestellten Implementation Links Dieses Kapitel soll Ihnen einen Schnellstart in C# ermöglichen. Es ist bewusst kurz gehalten. Ausführlichere Informationen und viele Codebeispiele nden Sie unter folgenden Links: Programmierhandbuch von Microsoft codeplex -.Net open source, insbesondere die Code-Snippets All-In-One Code Framework Viele Artikel und Beispielprojekte von.net-entwicklern: The Code Project Deutschsprachiges Tutorial: guide to C# von Golo Roden C# für Umsteiger: Learning C# from Java and C++ 59 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

60 4 Oce-Entwicklung Lernziele: Zugrundeliegende Technologie von Oce-Applikationen kennen Applikationen, die Oce-Dokumente erstellen oder editieren, entwickeln können Eigene Oce-Add-Ins entwickeln können Mit VS2010 ist die Kommunikation mit Oce einfacher geworden. Das Framework übernimmt die Kommunikation und stellt das komplette Objektmodell von beispielsweise Excel zur Verfügung. Leider erfolgt die Kommunikation weiterhin über COM-Interop. Erstellen Sie ein neues Excel-Addin und anschlieÿend eine Dependency-Diagram (auf Basis von Namespace oder Assembly). Sie erhalten eine Graphik ähnlich zu Abbildung 4.1. Abbildung 4.1: Excel-Addin: Interop Vor.Net 4.0 musste man mit jedem Projekt eine recht groÿe Interop-DLL, die das gesamte Interface enthielt mitliefern. Jetzt, kann Interop, reduziert auf die tatsächlich genutzten Teile, direkt in die eigene Assembly reinkompiliert werden. 4.1 Oce-Dokumente von auÿerhalb verändern oder erstellen Im TrainingKit nden Sie einige nützliche Labs und damit Beispiele, wie Sie Excel von C# aus steuern können. Folgendes Beispiel startet Excel und fügt Werte in eine neue Arbeitsmappe ein. Die Applikation selbst ist als Consolen-Applikation entwickelt. public class Account public int ID get; set; public double Balance get; set; public string AccountHolder get; set; static void Main(string[] args) var checkaccounts = CreateAccountList(); Listing 4.1: Oc-Werte in Excel einfügen checkaccounts.displayinexcel((account, cell) => 60

61 4.2 Excel-Addin cell.value2 = account.id; cell.get_offset(0, 1).Value2 = account.balance; cell.get_offset(0, 2).Value2 = account.accountholder; if (account.balance < 0) cell.interior.color = 255; cell.get_offset(0, 1).Interior.Color = 255; cell.get_offset(0, 2).Interior.Color = 255; ); private static List<Account> CreateAccountList() var checkaccounts = new List<Account> new Account ID = 1, Balance = , AccountHolder = "John Doe", new Account ID = 2, Balance = , AccountHolder = "Richard Roe", new Account ID = 3, Balance = , AccountHolder = "I Dunoe" ; return checkaccounts; static void DisplayInExcel(this IEnumerable<Account> accounts, Action<Account, Excel.Range> DisplayFunc) var x1 = new Excel.Application(); //see the Note below x1.workbooks.add(); x1.visible = true; x1.get_range("a1").value2 = "ID"; x1.get_range("b1").value2 = "Balance"; x1.get_range("c1").value2 = "Account Holder"; x1.get_range("a2").select(); foreach (var ac in accounts) DisplayFunc(ac, x1.activecell); x1.activecell.get_offset(1, 0).Select(); ((Excel.Range)x1.Columns[1]).AutoFit(); ((Excel.Range)x1.Columns[2]).AutoFit(); ((Excel.Range)x1.Columns[3]).AutoFit(); 4.2 Excel-Addin Zur Erstellung eines Excel-Addins gibt es eine entsprechende Vorlage in VS2010. Ein Excel-Add-In bendet sich in Excel, d.h. es läuft innerhalb von Excel. Daher ist es im Gegensatz zum letzten Beispiel nicht mehr notwendig, eine neue Excel-Applikation zu erstellen. Folgendes Code-Beispiel zeigt Ihnen, wie Sie einen Wert in eine Zelle einfügen und auslesen können. private void ThisAddIn_Startup(object sender, System.EventArgs e) Excel.Workbook wb = this.application.workbooks[1]; 61 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

62 4.2 Excel-Addin Excel.Worksheet ws = wb.worksheets[1]; var cell1 = ws.get_range("a1", Type.Missing); cell1.value2 = 2; var cell2 = ws.get_range("a2", Type.Missing); cell2.value2 = cell1.value2 * 42; Mit dem Managed Extensibility Framework (MEF) können Sie ihre eigenen Applikationen ähnlich für Add-Ins önen. 62 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

63 5 Datenbankanbindung Lernziele: Daten aus einer Datenbank auslesen und schreiben können Parametrisierte SQL-Befehle ausführen können LINQ-Abfragen auf eine Datenbank anwenden können Eine geeignete Zugrismöglichkeit auf eine Datenbank im jeweiligen Kontext auswählen können Die Basistechnologie aller.net-datenbankzugrie heiÿt ADO.Net. Diese steht im Fokus dieser Veranstaltung. ADO.Net bietet verschiedene Provider zum Zugri auf Datenbanken wie SQL Server, Oracle oder über OLE.Db und ODBC auf unterschiedliche Datenquellen. XML wird als Datenquelle zunehmend bedeutender, so dass auch hier ein performanter lesender, suchender und schreibender Zugri nötig ist. Über ADO.Net gibt es passende Interfaces, man muss jedoch für SQL Server und Oracle unterschiedliche Provider verwenden. 5.1.NET Framework-Datenanbieter Die.NET Framework-Datenanbieter sind Komponenten, die explizit für die Datenbearbeitung und den schnellen, vorwärts gerichteten, schreibgeschützten (d.h. nur lesenden) Zugri auf Daten entworfen wurden. Das Connection-Objekt sorgt für eine Verbindung mit einer Datenquelle. Mit dem Command-Objekt können Sie auf Datenbankbefehle denieren (ggf. parametrisiert), um Daten zurückzugeben oder zu ändern und gespeicherte Prozeduren (stored procedures) auszuführen. Zum Aufbau einer Datenbankverbindung brauchen Sie den sogenannten Connectionstring. Diese kann man sich mit der IDE erzeugen oder unter http: // nachschlagen. Listing 5.1: Datenzugri mit DataReader string connstring = "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;"; //mit using wird Connection und DataReader immer geschlossen! using (SqlConnection conn = new SqlConnection(connString)) SqlCommand cmd = conn.createcommand(); cmd.commandtext = "SELECT CustomerId, CompanyName FROM Customers"; conn.open(); Abbildung 5.1: DB: Technologien 63

64 5.2 DataSet Abbildung 5.2: Verbindungsorientierter DB-Zugri using (SqlDataReader dr = cmd.executereader()) if (myreader.hasrows) while (dr.read()) Console.WriteLine("0\t1", dr.getstring(0), dr.getstring(1)); dr.close(); //nur einen Wert auslesen: SqlCommand orderscmd = new SqlCommand("SELECT Count(*) FROM Orders", nwindconn); Int32 count = (Int32)ordersCMD.ExecuteScalar(); //mit Parametern int catid = 1; cmd = new SqlCommand("SELECT CategoryID, CategoryName FROM Categories WHERE CategoryID conn); cmd.paramters.addwithvalue("@categoryid, catid); //reader wie gehabt //mit Command-Parametern string sql = "SELECT * FROM users WHERE username=@username AND password=@password"; cmd = new SqlCommand(sql, conn); cmd.parameters.add("@username", SqlDbType.NVarChar, 16); cmd.parameters.add("@password", SqlDbType.NVarChar, 16); cmd.parameters.value["@username"] = username; cmd.parameters.value["@password"] = password; //reader wie gehabt conn.close(); 5.2 DataSet Das DataSet, ein aus einer Datenquelle abgerufener Datencache im Arbeitsspeicher, Das DataSet besteht aus einer Auistung von DataTable-Objekten, die Sie mit DataRelation-Objekten aufeinander beziehen können. In einer typischen Implementierung mit mehreren Ebenen werden die folgenden Schritte zum Erstellen und Aktualisieren eines DataSet und zum anschlieÿenden Aktualisieren der ursprünglichen Daten ausgeführt: 1 Das DataSet besteht aus einer Auistung von DataTable-Objekten, die Sie mit DataRelation-Objekten aufeinander beziehen können. 1. Erstellen Sie mithilfe eines DataAdapter jede DataTable in einem DataSet, und füllen Sie sie mit Daten aus einer Datenquelle c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

65 5.3 DataSet oder DataReader Abbildung 5.3: Verbindungsloser DB-Zugri 2. Ändern Sie die Daten in einzelnen DataTable-Objekten, indem Sie DataRow-Objekte hinzufügen, aktualisieren oder löschen. 3. Rufen Sie die GetChanges-Methode auf, um ein zweites DataSet zu erstellen, das nur die Änderungen an den Daten darstellt. 4. Rufen Sie die Update-Methode von DataAdapter auf, und übergeben Sie das zweite DataSet als Argument. 5. Rufen Sie die Merge-Methode auf, um die Änderungen aus dem zweiten DataSet mit dem ersten zusammenzuführen. 6. Rufen Sie AcceptChanges für das DataSet auf. Sie können auch RejectChanges aufrufen, um die Änderungen zu verwerfen. Listing 5.2: Update mit DataSet //connect to db SqlCommand myselectcommand = New SqlCommand("select * from customers", myconnection); SqlDataAdapter mysqldataadapter = new SqlDataAdapter(mySelectCommand); DataSet mydataset = new DataSet(); mysqldataadapter.fill(mydataset,"customers"); //anzeigen foreach (DataRow mydatarow in mydataset.tables["customers"].rows) Console.WriteLine(myDataRow["CustomerId"].ToString()); //löschen mydataset.tables["customers"].rows[0].delete(); //update mydataset.tables["customers"].rows[0]["contactname"]="peach"; mysqldataadapter.update(mydataset); 5.3 DataSet oder DataReader Das ADO.NET-DataSet wurde explizit für den Datenzugri unabhängig von Datenquellen entworfen. Aus diesem Grund kann es mit mehreren, unterschiedlichen Datenquellen, mit XML-Daten oder zum Verwalten von lokalen Anwendungsdaten verwendet werden. Das DataSet enthält eine Auistung von einem oder mehreren DataTable-Objekten, die aus Datenzeilen und -spalten sowie aus Primärschlüsseln, Fremdschlüsseln, Einschränkungen und Beziehungsinformationen über die Daten in den DataTable-Objekten besteht. Wenn Sie sich zwischen einem DataReader oder einem DataSet für die Anwendung entscheiden möchten, müssen Sie den für die Anwendung erforderlichen Funktionalitätstyp berücksichtigen. Verwenden Sie für folgende Zwecke ein DataSet: Lokales Zwischenspeichern von Daten in Ihrer Anwendung, um sie bearbeiten zu können. Wenn Sie nur die Ergebnisse einer Abfrage anzeigen müssen, ist der DataReader die bessere Alternative. 65 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

66 5.3 DataSet oder DataReader Abbildung 5.4: Datenbankzugri - Performanz Verschieben von Daten zwischen Ebenen oder von einem XML-Webdienst. Dynamisches Interagieren mit Daten, wie Datenbindung an ein Windows Forms-Steuerelement, oder Kombinieren von und Erstellen einer Beziehung zwischen Daten aus mehreren Quellen. Ausführen umfangreicher Datenverarbeitungsschritte ohne eine oene Verbindung zur Datenquelle. Dadurch wird die Verbindung zur Nutzung durch andere Clients freigegeben. Wenn Sie die von DataSet bereitgestellten Funktionen nicht benötigen, können Sie die Leistung Ihrer Anwendung verbessern, indem Sie mithilfe des DataReader die Daten als schreibgeschützte Vorwärtsdaten zurückgeben. Obwohl der DataAdapter den DataReader zum Füllen des DataSet-Inhalts verwendet (siehe Auüllen eines DataSets mit einem DataAdapter-Objekt), können Sie die Leistung erhöhen, wenn Sie den DataReader verwenden. Dies ist möglich, weil Sie den Arbeitsspeicher, der für das DataSet erforderlich ist, nicht benötigen und die Verarbeitung, die zum Erstellen und Füllen des DataSet-Inhalts nötig ist, überüssig ist. Neben den vorgestellten DB-Zugrismöglichkeiten bietet das.net Framework mit dem Entity Framework (EF) einen in VS gut integrierten OR-Mapper. Eine gut verständliche Einführung nden Sie unter microsoft.com/de-de/library/bb aspx. Wie bei den Tests gibt es auch hier eine verbreitete und in Java verfügbare Alternative: Hibernate, bzw. für.net NHibernate. Neben dem EF gibt es noch weitere Klassenbibliotheken für den Datenbankzugri. Einen guten Vergleich liefert folgender Artikel: Daten im (Zu- )Gri mit.net: DataReader, DataSet oder ORM?. Aus diesem Artikel stammt auch Abbildung 5.4, die die Performance der diskutierten DB-Zugrismöglichkeiten vergleicht. 66 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

67 5.4 P4* - Datenbanken und Addins 5.4 P4* - Datenbanken und Addins Abgabetermin: Aufgabe P4.1 Erstellen Sie eine SQL-Datenbank für Ihren Audio-Player. Wählen Sie die DB-Struktur so, dass auch Videodateien einfach hinzugefügt werden können. Normalisieren Sie die Datenbank. Aufgabe P4.2 Fügen Sie als Persistierung zur Serialisierung die erstellte SQL-Datenbank hinzu. Aufgabe P4.3 Erstellen Sie eine einfache Consolen-Applikation, die... (a) Mit einem DataReader Daten ausliest, die Sie auf der Console ausgeben. (b) Mit einem DataSet Daten ausliest und Änderungen in die DB schreibt. (c) Verwenden Sie zum Schreiben von Daten Kommandparameter. Warum sind parametrisierte Befehle sinnvoll? (d) Verwenden Sie einen DataAdapter sinnvoll. (e) Schreiben Sie 1000 Datensätze in eine Tabelle. (f) Implementieren Sie einen einfachen Performanztest, der beim Lesen von 1000 Datensätzen DataReader mit DataSet vergleicht. Aufgabe P4.4 Lesen Sie Daten aus einer Datenbank aus und schreiben Sie sie in eine neue Excel-Datei. Aufgabe P4.5 Erstellen Sie ein Excel-Addin, bei dem Sie einen SQL-Servernamen eingeben können, daraufhin zeigen Sie eine Combo-Box mit allen Datenbanken an und bei Auswahl einer DB eine ComboBox mit den darin enthaltenen Tabellen. Ein Click auf einen Import-Button importiert diese Daten in das aktuelle Tabellenblatt. 67 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

68 6 Windows Presentation Foundation Lernziele: Wesentliche Controls zur Oberächengestaltung bei Desktop-Anwendungen in.net kennen lernen und zielgerichtet einsetzen können Prinzip der Datenbindung in.net am Beispiel von WPF-Controls beschreiben und anwenden können Architektur für gröÿere Projekte mit ihren Vor- und Nachteilen kennen und mit Hilfe von Beispielen erläutern können Windows Presentation Foundation (WPF) wird zur Oberächenentwicklung auf dem Desktop verwendet. Ursprünglich wurde hierfür die Technologie WinForm eingesetzt. Seit 2010 entwickelt Microsoft jedoch WinForm nicht mehr weiter und sieht die Zukunft der Desktop-Entwicklung in WPF. WPF ist eine Klassenbibliothek, die seit.net 3.0 im Jahr 2006 zum.net Framework gehört. WPF nutzt eine deklarative Programmiersprache (XAML), zur Beschreibung von Oberächen. Objektmodell und XAML können 1:1 aufeinander abgebildet werden, so dass Entwickler sich entscheiden können, welchen Teil sie in C# und welchen Teil sie in XAML implementieren. Das einfache Zusammenklicken von Oberächen und das Anpassen in XAML fügt sich gut zueinander in WinForm sollte man den von VisualStudio erzeugten Code besser nicht anfassen. Die Grakausgabe ist vektorbasiert, damit ist ein Zoomen verlustfrei möglich. 6.1 XAML XAML ist eine deklarative Beschreibungssprache für Oberächen auf der Basis von XML. XAML steht für Extensible Application Markup Language. Sie wird auch zur Denition von Workows in Windows Workow foundation (WF) verwendet auf die wir in dieser Veranstaltung nicht eingehen. Dieser deklarative Ansatz wird auch von anderen verfolgt, wie folgende Auswahl zeigt: XUL: XML User Interface Language (Mozilla Projekt) UIML: OASIS User Interface Markup Language MXML von Adobe Zur Laufzeit wird aus XAML die entsprechenden Objekte der.net-klassen erzeugt. 6.2 Architektur von Windows Presentation Foundation und das Programmiermodell Wenn Sie ein neues WPF-Projekt anlegen, werden drei wichtige Referenzen eingebunden: PresentationFramework.dll, PresentationCore.dll, mscorlib.dll und WindowsBase.dll. Diese Bibliotheken sind die Hauptkomponenten von WPF. Sie können sich einfach einen guten Überblick über die Architktur verschaen, in dem Sie folgende Schritte ausführen: 1. Erzeugen Sie ein neues WPF-Projekt. 2. Erzeugen Sie ein benutzerdeniertes Abhängigkeitsdiagramm. Wählen Sie Assemblies, Typen und Extern aus. 3. Erkunden Sie die einzelnen Komponenten im Diagramm. 4. Erkunden Sie die Assemblies im ObjectExplorer. 68

69 6.3 Steuerelemente und Layout Abbildung 6.1: WPF Architektur Abbildung 6.1 zeigt die Hauptkomponenten von WPF. PresentationFramework enthält die top-level Typen, z.b. auch die weiter unten betrachtete Basisklasse FrameworkElement. PresentationCore enthält Basistypen wie UIElement. WindowsBase enthält das DependencyObject. Die Komponente milcore kommuniziert direkt mit DirectX und ist für das Rendern zuständig. Microsoft hat sich dafür entschieden, milcore zur besseren Performance als unmanaged Code zu entwickeln, sie läuft also auÿerhalb der CLR. Abbildung 6.2 zeigt die Vererbungshierarchie von MainWindow. Dies können Sie einfach erzeugen, in dem Sie im Projectexplorer einen Rechtsklick auf die cs-datei machen, sich das Klassendiagramm erzeugen lassen und nun iterativ mit Rechtsklick im Diagramm die Basisklasse anzeigen lassen. Abbildung 6.3 zeigt eine Übersicht wesentlicher GUI-Elemente, die von FrameworkElement erben. Hat man ein Projekt aufgrund der WPF-Vorlage erstellt, so ist dies direkt lauähig, es wird ein leeres Fenster angezeigt. Schaut man in den Code rein, so vermisst man ein ähnliches Konstrukt wie bei der Console-Anwendung: Im Code ndet sich keine Main-Funktion. Önen Sie im Datei-Explorer das beim Build erzeugte Verzeichnis obj, dort nden Sie eine Datei App und darin enthalten ist eine Main-Funktion wie unten wiedergebeben. [System.STAThreadAttribute()] [System.Diagnostics.DebuggerNonUserCodeAttribute()] public static void Main() WpfApplication1.App app = new WpfApplication1.App(); app.initializecomponent(); app.run(); Listing 6.1: WPF Main In der Datei App.xml denieren Sie mit StartupUri, welche XAML-Datei zuerst geladen wird. 6.3 Steuerelemente und Layout Üblicherweise enthält das Hauptfenster einen Layoutcontainer, also ein Grid, ein Stack- Dock- oder Wrap-Panel oder ein Canvas und darin enthaltenen Kindobjekten. In der Toolbox nden Sie eine Reihe von nützlichen Controls, aus denen Sie Ihre Oberäche zusammen setzen können. Dies können Sie per Drag&Drop, in XAML oder auch in C# tun. Ziehen Sie beispielsweise ein Button-Control auf MainWindow, so wird folgender XAML- Code erzeugt: <Grid Name="mainGrid" > <Button Content="Button" Height="41" HorizontalAlignment="Left" Margin="74,70,0,0" Name="button1" VerticalAlignment="Top" Width="141" Click="button1_Click" /> </Grid> 69 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

70 6.3 Steuerelemente und Layout Abbildung 6.2: WPF Vererbungshierarchie Folgender C#-Code erzeugt analog einen Button und fügt ihn in das Grid ein: Button b = new Button(); b.name = "button2"; b.content = "Button 2"; b.height = 41; b.width = 141; this.maingrid.children.add(b); Beachten Sie, dass für Content ein String genutzt wurde, Sie hätten auch andere Elemente wählen können, denn ein Button kann auch andere Controls, Bilder etc. enthalten. Den Aufbau existierender Applikationen können Sie gut mit dem freien Werkzeug Snoop erkunden. Barrierefreiheit ist nicht nur im Web wichtig, sondern bei jeder Softwareentwicklung. Vergeben Sie daher für alle Controls einen sinnvollen Titel und eine sinnvolle Tab-Folge Container Container werden für das Layout, also die grobe Aufteilung der einzelnen Fenster verwendet. Im Prinzip nden Sie hier ähnliche Positionierungsmethoden wieder, die sie in EWA bei CSS kennen gelernt haben: Canvas (absolute Positionierung): Bei Canvas kann immer nur eine Positionsart deniert werden, Top oder Left oder Bottom oder Right. StackPanel (Blockelemente untereinander): Das Stackpanel funktioniert wie der Name schon sagt, wie ein Stapel, die Elemente werden untereinander angeordnet, dabei können Ränder deniert werden. Margin wird anders als bei CSS in der Reihenfolge links, oben, rechts, unten angegeben. Wird keine Breite deniert, dann gehen die Elemente über die gesamte Breite des StackPanels. DockPanel: Die Controls können an den Rändern angedockt werden. Dies können mehrere hintereinander sein. Auch, wenn eine Breite angegeben wird, passt kein weiteres Element daneben hierfür wird ein WrapPanel benötigt. Falls die Standardeinstellung LastChildFill gewählt wird, dann füllt das letzte Kindeelement den verbleibenden Platz. WrapPanel (oat): Die Elemente können nebeneinander oaten. Ist keine Breite deniert, so nehmen sie die Gröÿe ein, die der Inhalt braucht. 70 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

71 6.3 Steuerelemente und Layout Abbildung 6.3: FrameworkElement, Quelle: WinfWiki Grid (Tabelle): Zunächst müssen die Zeilen und Spalten deniert werden (es reicht auch eines). Danach werden diese gefüllt. Mit GridSplitter kann die Benutzerin die Gröÿe selbst anpassen. Folgendes Code-Beispiel verbindet alle Layouts und Abbildung 6.4 zeigt das anfängliche Aussehen. Listing 6.2: Layout Controls ï¾<window x:class="wpflayoutcontainer.mainwindow" xmlns=" xmlns:x=" Title="Layout Container" Height="250" Width="900"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="200" /> <ColumnDefinition Width="200" /> <ColumnDefinition Width="200" /> <ColumnDefinition Width="200" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="30" /> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Rectangle Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="4" Fill="Silver" /> <GridSplitter ResizeDirection="Rows" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="4" Background="Gray" Width="800" Height="5" HorizontalAlignment="Left" VerticalAlignment="Top" /> <Canvas Grid.Row="1" Grid.Column="0"> <Label Content="top absolut positioniert mit Canvas" Canvas.Top="20" /> <Button Name="DisableMouseEnterBtn" Content="deactivate mouse over" Canvas.Bottom="5" Click=" DisableMouseEnterBtn_Click" /> </Canvas> <GridSplitter Grid.Row="1" Grid.Column="0" Background="Red" Width="5"/> <StackPanel Grid.Row="1" Grid.Column="1"> <Label Grid.Row="1" Content="erstes Label" Margin="5" BorderBrush="#FF190000" BorderThickness="2" /> <Label Content="zweites Label" Margin="30" BorderBrush="#FF190000" BorderThickness="2" /> <Label Content="drittes Label (kleiner)" Margin="5" Width="150" BorderBrush="#FF190000" BorderThickness ="2"/> </StackPanel> <GridSplitter Grid.Row="1" Grid.Column="1" Background="Red" Width="5"/> <DockPanel Grid.Row="1" Grid.Column="2"> <Label Content="dock Top" DockPanel.Dock="Top" BorderBrush="#FF190000" BorderThickness="2" /> <Label Content="dock Bottom" DockPanel.Dock="Bottom" BorderBrush="#FF190000" BorderThickness="2" /> 71 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

72 6.3 Steuerelemente und Layout <Label Content="dock Top 2" DockPanel.Dock="Top" BorderBrush="#FF190000" BorderThickness="2" /> <Label Content="dock Left" DockPanel.Dock="Left" BorderBrush="#FF190000" BorderThickness="2" /> <Label Content="last child fill" DockPanel.Dock="Top" BorderBrush="#FF190000" BorderThickness="2" /> </DockPanel> <GridSplitter Grid.Row="1" Grid.Column="2" Background="Red" Width="5"/> <WrapPanel Name="WrapPanelWithEvents" Grid.Row="1" Grid.Column="3" MouseEnter=" WrapPanelWithEvents_MouseEnter" ButtonBase.Click="WrapPanelWithEvents_Click"> <Label Content="label 1" BorderBrush="#FF190000" BorderThickness="2" /> <Label Name="lblWithMouseEnter" Content="mouse enter:" BorderBrush="#FF190000" BorderThickness="2" MouseEnter="lblWithMouseEnter_MouseEnter" /> <Label Content="label 3 mit Breite" Width="200" BorderBrush="#FF190000" BorderThickness="2" /> <Label Content="label 3..." BorderBrush="#FF190000" BorderThickness="2" /> <Button Name="btnClick" Content="click" Click="btnClick_Click" /> </WrapPanel> </Grid> </Window> Abbildung 6.4: WPF Layout Beispiel Frage 6.1 Nennen Sie jeweils ein Beispiel, bei dem Sie ein DockPannel bzw. ein StackPannel bzw. ein Grid sinnvoll einsetzen würden. Wenn alle Controls erzeugt wurden, erhält man einen Baum. Es wird zwischen dem logischen und dem visuellen Baum unterschieden Logischer Baum Der logische Elementbaum enthält alle von Ihnen eingefügten Steuerelemente. Mit dem Einfügen eines Controls können indirekt weitere Elemente eingefügt werden Visueller Baum Der visuelle Baum enthält zusätliche Elemente wie Border, ContentPresenter oder TextBlock. Der folgende Code nutzt die in.net vorhandenen Klassen VisualTreeHelper und LogicalTreeHelper zum Anzeigen der Elementbäume des unteren Panels. Listing 6.3: Erzeugen des visuellen und logischen Elementbaumes private void filltrees() TreeViewItem rootvi = new TreeViewItem(); rootvi.header = "Visueller Elementbaum des unteren Panels:"; vitree.items.add(rootvi); 72 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

73 6.3 Steuerelemente und Layout showvisualtree(rootvi, demopanel); TreeViewItem rootlo = new TreeViewItem(); rootlo.header = "Logischer Elementbaum des unteren Panels:"; lotree.items.add(rootlo); showlogicaltree(rootlo, demopanel); private void showvisualtree(treeviewitem parentitem, DependencyObject parentobj) TreeViewItem item = new TreeViewItem(); item.header = parentobj.gettype().tostring(); parentitem.items.add(item); for(int i=0; i< VisualTreeHelper.GetChildrenCount(parentObj); i++) showvisualtree(item, VisualTreeHelper.GetChild(parentObj, i)); private void showlogicaltree(treeviewitem parentitem, DependencyObject parentobj) TreeViewItem item = new TreeViewItem(); item.header = parentobj.gettype().tostring(); parentitem.items.add(item); foreach (object obj in LogicalTreeHelper.GetChildren(parentObj)) DependencyObject dep = obj as DependencyObject; if (dep!= null) showlogicaltree(item, dep); Routed Events Erinnern Sie sich noch daran, wie Ecma-Skript Ereignisse von ineinander geschachtelten Elementen verarbeitet? Was passiert beispielsweise bei folgendem Code, wenn Sie auf P bzw. DIV klicken? <div onclick="this.style.background='red';">div <p onclick="this.style.background='blue';>p</p> </div> Und, was passiert bei folgendem Code: Listing 6.4: JS Ereignisweiterleitung <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" " <html xmlns=" xml:lang="en" lang="en"> <head> <title>ereignisweiterleitung</title> <script type="text/javascript"> function bubble(id) window.alert( "bubble " + id ); function capture(id) window.alert( "capture " + id ); function ini() document.getelementbyid("table1").addeventlistener( "click", function()bubble("table1"), false ); // - use capture = false document.getelementbyid("table1").addeventlistener( "click", function()capture("table1"), true ); document.getelementbyid("tr1").addeventlistener( "click", function()bubble("tr1"), false ); // - use capture = false document.getelementbyid("tr1").addeventlistener( "click", function()capture("tr1"), true ); document.getelementbyid("td1").addeventlistener( "click", function()bubble("td1"), false ); // - use capture = false document.getelementbyid("td1").addeventlistener( "click", function()capture("td1"), true ); </script> 73 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

74 6.3 Steuerelemente und Layout </head> <body onload="ini();"> <table id="table1"> <tr id="tr1"><td id="td1"> </td><td> </td></tr> <tr><td>3</td><td>4</td></tr> </table> <p>hello World!</p> </body> </html> Hier werden die Ereignisse zunächst von auÿen nach innen und dann wieder von innen nach auÿen geleitet. Listing 6.5: Layout Controls - EventHandler 20 public partial class MainWindow : Window public MainWindow() InitializeComponent(); 25 AssingMyRoutedEvent(); private void lblwithmouseenter_mouseenter(object sender, MouseEventArgs e) Label tmp = sender as Label; 31 if (tmp!= null) 32 tmp.content = tmp.content + " <> "; 33 e.handled = false; private void WrapPanelWithEvents_MouseEnter(object sender, MouseEventArgs e) MessageBox.Show("wrap panel, mouse enter"); //System.Diagnostics.Debug.WriteLine("wrap panel, mouse enter"); private void DisableMouseEnterBtn_Click(object sender, RoutedEventArgs e) lblwithmouseenter.mouseenter -= this.lblwithmouseenter_mouseenter; 45 lblwithmouseenter.content = "inactive"; 46 WrapPanelWithEvents.MouseEnter -= this.wrappanelwithevents_mouseenter; private void btnclick_click(object sender, RoutedEventArgs e) Button tmp = sender as Button; 52 if (tmp!= null) 53 tmp.content = tmp.content + " <r> "; private void WrapPanelWithEvents_Click(object sender, RoutedEventArgs e) MessageBox.Show("wrap panel button click"); Zunächst ist festzustellen, dass es in WPF zwei Arten von Events gibt. Ereignisse, wie MouseEnter entsprechen den bisher kennen gelernten Ereignissen. Von innen nach auÿen wird nach einem Handler gesucht. Ist dieser gefunden, ist die Behandlung erledigt - es können natürlich meherere EventHandler für das gleiche Ereignis desselben Controls registriert werden. In Listing 6.2 wird in den Zeilen 39 und 41 beispielsweise sowohl für ein Label als auch für den zugehörigen Container ein MouseEnter-Ereignishandler (Zeilen 27 und 36 in Listing 6.7) registriert. Erst durch Zeile 32, in der Handled auf false gesetzt wird, wird ein Weiterreichen erzwungen. Nun wird innerhalb des logischen Elementbaumes geschaut, welche Elternelemente ein EreignisHandler für MouseEnter registriert haben. Ob nun die Strategie, tunneling oder bubbling verwendet wird, liegt an der Art des Ereignisses, Preview-Ereignisse, wie PreviewMouseDown werden getunnelt, während MouseDown und ähnliche Ereignisse mit bubbling den Baum durchlaufen. Möchten wir nun auf ein Click-Ereignis auf den im Panel enthaltenen Button reagieren, so haben wir bei der momentan angezeigten MessageBox das Problem, dass es nie zum Click-Ereignis kommt. Daher gibt es einen zusätzlichen Button, der die EventHandler für MouseEnter wieder entfernt (siehe Zeile 41). Alternativ hätten wir die Ausgabe auch einfach auf das Debug-Output-Fenster umleiten können (siehe auskommentierter Code in Zeile 38). In Listing 6.7 werden EventHandler in den Zeilen 39 und 44 von Listing 6.2 für ein Button.Click 74 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

75 6.3 Steuerelemente und Layout registriert. Die generierten EventHandler enthalten nun einen Parameter vom Typ RoutedEventArgs (siehe Zeile 48 in Listing 6.7). Wie der Name vermuten lässt, werden diese Events per default weitergeleitet. Hier müsste ich also Handled explizit auf True setzen, um die Weiterleitung zu unterdrücken. Schauen wir uns die Basis für beide Events an (wieder in der generierten Datei MainWindow.g.cs zu nden, dann sehen wir folgende Denitionen für das WrapPanel und mit F12 erhalten wir die zugehörigen in.net Denitionen: Listing 6.6: WPF Main 1 //MouseEnter 2 this.wrappanelwithevents.mouseenter += new System.Windows.Input.MouseEventHandler(this. WrapPanelWithEvents_MouseEnter); 3 //.Net Denitions 4 namespace System.Windows public class UIElement public event MouseEventHandler MouseEnter;... 5 namespace System.Windows.Inputpublic delegate void MouseEventHandler(object sender, MouseEventArgs e); 6 7 //Button.Click 8 this.wrappanelwithevents.addhandler(system.windows.controls.primitives.buttonbase.clickevent, new System.Windows. RoutedEventHandler(this.WrapPanelWithEvents_Click)); 9 10 //.Net Denitions 11 namespace System.Windows public class UIElement public void AddHandler(RoutedEvent routedevent, Delegate handler); namespace System.Windows.Controls.Primitivespublic abstract class ButtonBase...public static readonly RoutedEvent ClickEvent; namespace System.Windows public delegate void RoutedEventHandler(object sender, RoutedEventArgs e); Sie sehen, dass in Zeile 2 ein MouseEventHandler, also ein event im eigentlichen Sinne übergeben wird (Zeile 4). Während bei Button.Click ein ClickEvent, also ein RoutedEvent übergeben wird. Wenn Sie sich beim Debuggen bei Zeile 12 das RoutedEvent ansehen, können Sie die verwendete Strategie sehen: Bubble. Diese kann bei RoutedEvents generell deniert werden. Sie können sich analog zu Events auch eigene RoutedEvents denieren. Den prinzipiellen Aufbau zeigt folgendes Listing, das sich an Listing 6.7 anschlieÿt. Listing 6.7: Layout Controls - EventHandler RoutedEventArgs mye = new RoutedEventArgs(MyRoutedEvent, this); WrapPanelWithEvents.RaiseEvent(mye); public static readonly RoutedEvent MyRoutedEvent = EventManager.RegisterRoutedEvent("MyEvent", RoutingStrategy.Tunnel, typeof(routedeventhandler), typeof(button)); private void AssingMyRoutedEvent() this.wrappanelwithevents.addhandler(mainwindow.myroutedevent, new System.Windows.RoutedEventHandler( this.wrappanelwithevents_myroutedevent)); private void WrapPanelWithEvents_MyRoutedEvent(object sender, RoutedEventArgs e) MessageBox.Show("wrap panel my routed event"); Frage 6.2 Werden Routed Events entlang des visuellen oder entlang des logischen Baums weitergeleitet? Frage 6.3 Nehmen Sie zu folgender Aussage Stellung: Routed Events werden in.net zunächst von innen nach auÿen (bubble) entlang des visuellen Baumes weitergereicht und anschlieÿend entlang des logischen Baumes von auÿen nach innen (tunnel) durchgereicht. 75 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

76 6.3 Steuerelemente und Layout Klasse ApplicationCommands NavigationCommands EditingCommands MediaCommands ComponentCommands Beispiele Close, Cut, Copy, Paste, Save, Print BrowseForward, BrowseBack, Zoom, Search AlignXXX, MoveXXX, SelectXXX Play, Pause, NextTrack, IncreaseVolume, Record, Stop MoveXXX, SelectXXX, ScrollXXX, ExtendSelectionXXX Tabelle 6.1: WPF Commands, Quelle: Understanding Routed Events and Commands In WPF Command Commands bilden die Möglichkeit, die Oberäche von der eigentlichen Applikationslogik zu entkoppeln. Die üblichen Oberächenkommandos, wie Copy, Paste, Cut stellt.net vorimplementiert zur Verfügung. Alles, was man hierfür tun muss, ist den entsprechenden Command im XAML-Attribut Command anzugeben: <MenuItem Command="Copy" /> Hier wird also keine zusätzliche Programmierung benötigt. Tabelle 6.1 listet einige vorhandene Commands auf. Mit diesen vordefnierten Commands lässt sich ein Editor implementieren. Frage 6.4 Welche Controls unterstützen die Eigenschaft Command? Auf selbst denierte Commands gehe ich in Abschnitt 6.6 auf Seite 80 ein. 76 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

77 6.4 Praktikum P5* - WPF Oberäche 6.4 Praktikum P5* - WPF Oberäche Abgabetermin: Aufgabe P5.1 Analysieren Sie mit Snoop eine WPF-Anwendung Ihrer Wahl. Notieren Sie den groben Aufbau der GUI. Aufgabe P5.2 Wodurch unterscheiden sich der visuelle und der logische Element-Baum einer WPF-Oberäche? Aufgabe P5.3 Setzen Sie das in Abbildung 6.5 gezeigte Layout um. Abbildung 6.5: Layoutaufgabe (a) Fertigen zunächst eine Skizze an. (b) Implementieren Sie das Layout in WPF. (c) Suchen Sie nach SpellingError und fügen Sie eine Korrekturhilfe hinzu. (d) Fügen Sie exemplarisch die Commands Cut, Copy, und Paste hinzu. Aufgabe P5.4 Fügen Sie Ihrem Audio-Player eine geeignete WPF-Oberäche hinzu. 77 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

78 6.5 Datenbindung 6.5 Datenbindung Bei der Datenbindung in WPF geht es darum, Oberächenelemente (Controls) zum Anzeigen und Ändern von Daten zu verwenden. Abbildung 6.6 zeigt den prinzipiellen Aufbau der Datenbindung. Abbildung 6.6: WPF Datenbindung, Prinzip Auf der GUI-Seite wird dabei ein DependencyProperty benötigt und auf der Datenseite eine Klasse, die das Interface INotifyPropertyChanged implementiert DependencyProperty Eine DependencyProperty wurde in WPF zur einfacheren Umsetzung von Datenbindung und zur einfachen Umsetzung einheitlicher Styles eingeführt. Es handelt sich hier um eine Property, die syntaktisch genauso angesprochen wird, die jedoch über entsprechende Setter- und Getter-Methoden verfügt, die Änderungsevents auslösen können. Für eine Textbox ist dies beispielsweise: //Der Bezeichner für die System.Windows.Controls.TextBox.Text Abhängigkeitseigenschaft. public static readonly DependencyProperty TextProperty; DependencyProperty ist immer als static readonly zu deklarieren. Frage 6.5 Wodurch unterscheidet sich ein DependencyProperty von einem normalen Property? INotifyPropertyChanged Die Schnittstellendenition für INotifyPropertyChanged bendet sich im Namensraum System.ComponentModel und beinhaltet folgende Denition: //Benachrichtigt Clients, dass ein Eigenschaftswert geändert wurde. public interface INotifyPropertyChanged //Tritt ein, wenn sich ein Eigenschaftswert ändert. event PropertyChangedEventHandler PropertyChanged; Wenn wir für eine einfache Klasse Student diese Schnittstelle implementieren möchten, so müssen wir das event einfügen. Wenn wir noch das event bei Änderungen auslösen, dann kann die GUI oder andere Listener diese Änderungen auch mitbekommen. Den zugehörigen Code zeigt Listing 6.8 Listing 6.8: INotifyPropertyChanged public string Name get return _name; set _name = value; OnPropertyChanged("Name"); public string Mark get return _mark; set _mark = value; System.Diagnostics.Debug.WriteLine("mark changed to " + _mark); OnPropertyChanged( "Mark"); 78 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

79 6.5 Datenbindung protected virtual void OnPropertyChanged(string propname) if (PropertyChanged!= null) //at least one is interested PropertyChanged(this, new PropertyChangedEventArgs(propName)); Die Klasse Student ist als Singleton implementiert, um später zu zeigen, die Änderungen können von verschiedener Seite geändert werden und die entsprechenden Bindungen spiegeln diese Änderungen wider. Frage 6.6 Wäre es auch möglich, in der Schnittstelle INotifyPropertyChanged anstelle von event das Schlüsselwort delegate zu verwenden? Binding Jetzt können wir recht einfach eine Datenbindung herstellen, wie Listing 6.9 zeigt. Listing 6.9: INotifyPropertyChanged 31 _student = Student.GetInstance(); 32 lblname.content = _student.name; 33 Binding bindingmark = new Binding("Mark"); //path = name of property 34 bindingmark.source = _student; 35 bindingmark.mode = BindingMode.TwoWay; 36 bindingmark.updatesourcetrigger = UpdateSourceTrigger.PropertyChanged; //with every key press 37 txtmark.setbinding(textbox.textproperty, bindingmark); private void btn1_click(object sender, RoutedEventArgs e) _student.mark = "1.0"; private void btn2_click(object sender, RoutedEventArgs e) _student.mark = "2.0"; private void btnopenwindow_click(object sender, RoutedEventArgs e) DataContextExample w = new DataContextExample(); 54 w.show(); In Zeile 33 wird dem Konstruktor der Klasse Binding als Pfad zur Bindungsquelle der Propertyname übergeben, an den das Control gebunden werden soll. Zeile 34 legt die eigentliche Datenquelle fest, die Instanz _student. Zeile 35 deniert, die Bindung in beide Richtungen, Änderungen von den Daten zum GUI-Control und umgekehrt werden mitgeteilt. Zeile 36 sagt schlieÿlich, dass jede Änderung im Control direkt kommuniziert wird, in diesem Fall also jede Tastatureingabe. Bemerkung: Das Projekt kann kompilieren und im starten, auch wenn Sie in Zeile 33 vielleicht einen Tippfehler gemacht haben und die Property so nicht existiert. Dies erzeugt beim normalen Compilieren nicht einmal eine Warnung. Erst zur Laufzeit, also z.b. beim Starten des Projekts im Debug-Modus, erhalten Sie folgende Fehlermeldung im Output-Fenster: 79 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

80 6.5 Datenbindung System.Windows.Data Error: 40 : BindingExpression path error: 'Markx' property not found on 'object' ''Student' ( HashCode= )'. BindingExpression:Path=Markx; DataItem='Student' (HashCode= ); target element is 'TextBox' (Name='txtMark'); target property is 'Text' (type 'String') Die Zeilennummer bezieht sich dabei leider nicht auf Ihren Code. Abbildung 6.7 zeigt den prinzipiellen Aufbau der Datenbindung unter Verwendung der eingeführten Schnittstellen und Klassen. Die Methode SetBinding stellt die Verbindung her. Abbildung 6.7: WPF Datenbindung, Prinzip aus Codesicht, Quelle: Christian Mosers WPF Tutorial.net Merke 9 (Datenbindung) Die Datenbindung erfordert ein Objekt (Quelle) einer Klasse, die INotifyPropertyChanged implementiert ein Objekt (Control) mit einem DependencyProperty ein Bindungsobjekt (Binding) den Aufruf der Methode SetBinding des Controls Frage 6.7 Wann wird bei einer Datenbindung wo ein Listener beim Event von INotifyPropertyChanged registriert bzw. deregistriert? Frage 6.8 Bleibt einer Datenbindung zu einer Datenbank die Verbindung erhalten oder nicht? DataContext Neben der bisher aufgeführten Möglichkeit der Datenbindung auf Code-Ebene, kann eine Datenbindung auch in XAML auf Basis eines DataContext erfolgen: _student = Student.GetInstance(); this.datacontext = _student; Listing 6.10: DataContext 80 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

81 6.6 MVVM Die Denition der Datenbindung erfolgt in XAML: Listing 6.11: Binding in XAML mit DataContext <TextBox Name="txtMark" Text="Binding Path=Mark, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"/> Frage 6.9 Was sind die wesentlichen Eigenschaften und Methoden von DataContext und wie unterscheidet sich dieser Ansatz von einer Datenbindung auf Basis von INotifyPropertyChanged? 6.6 MVVM Abbildung 6.8: MVVM, Quelle: Nikhil Kothari CodeBehind ist für Unit-Tests nicht erreichbar, kann also nicht automatisch getestet werden. Dieser Code ist auch neu zu programmieren, wenn Sie beispielsweise die Applikation auch für mobile Endgeräte oder das Web verfügbar machen möchten. Das zugehörige Pattern für WPF heiÿt Model View View Model und wird mit MVVM abgekürzt. Die Basis dieses Patterns sind Datenbindung und Command. Als Denkhilfe können Sie folgende Vereinfachung verwenden: MVVM ist eine auf WPF angepasste Version von MVC. Der Controller wird so verpackt, dass WPF mit DataBinding und Commands auf CodeBehind verzichten kann. Betrachten wir hierzu ein einfaches Beispiel. Die Funktionalität der Applikation ist zu Demonstrationszwecken stark reduziert. Ein Model verwaltet seine Daten. Über die in Listing 6.12 denierte Funktionen könnten auch Validierungs- oder DB-Probleme integriert werden. public interface IStudentProvider void Add(Student student); IEnumerable<Student> GetStudents(); int Count get; public class MockStudentProvider : IStudentProvider private List<Student> _students; public MockStudentProvider() _students = new List<Student>(); _students.add(new Student("Asterix", "1.0")); _students.add(new Student("Obelix", "3.0")); public void Add(Student student) _students.add(student); Listing 6.12: Einfaches Model für MVVM 81 c Dr. Ute Blechschmidt-Trapp,.Net Framework und C# SS 2011

Es sollte die MS-DOS Eingabeaufforderung starten. Geben Sie nun den Befehl javac ein.

Es sollte die MS-DOS Eingabeaufforderung starten. Geben Sie nun den Befehl javac ein. Schritt 1: Installation des Javacompilers JDK. Der erste Start mit Eclipse Bevor Sie den Java-Compiler installieren sollten Sie sich vergewissern, ob er eventuell schon installiert ist. Gehen sie wie folgt

Mehr

Er musste so eingerichtet werden, dass das D-Laufwerk auf das E-Laufwerk gespiegelt

Er musste so eingerichtet werden, dass das D-Laufwerk auf das E-Laufwerk gespiegelt Inhaltsverzeichnis Aufgabe... 1 Allgemein... 1 Active Directory... 1 Konfiguration... 2 Benutzer erstellen... 3 Eigenes Verzeichnis erstellen... 3 Benutzerkonto erstellen... 3 Profil einrichten... 5 Berechtigungen

Mehr

Einführung in die Java- Programmierung

Einführung in die Java- Programmierung Einführung in die Java- Programmierung Dr. Volker Riediger Tassilo Horn riediger horn@uni-koblenz.de WiSe 2012/13 1 Wichtig... Mittags keine Pommes... Praktikum A 230 C 207 (Madeleine + Esma) F 112 F 113

Mehr

Installation und Inbetriebnahme von Microsoft Visual C++ 2010 Express

Installation und Inbetriebnahme von Microsoft Visual C++ 2010 Express Howto Installation und Inbetriebnahme von Microsoft Visual C++ 2010 Express Peter Bitterlich Markus Langer 12. Oktober 2012 Zusammenfassung Dieses Dokument erklärt Schritt für Schritt die Installation

Mehr

! " # $ " % & Nicki Wruck worldwidewruck 08.02.2006

!  # $  % & Nicki Wruck worldwidewruck 08.02.2006 !"# $ " %& Nicki Wruck worldwidewruck 08.02.2006 Wer kennt die Problematik nicht? Die.pst Datei von Outlook wird unübersichtlich groß, das Starten und Beenden dauert immer länger. Hat man dann noch die.pst

Mehr

Suche schlecht beschriftete Bilder mit Eigenen Abfragen

Suche schlecht beschriftete Bilder mit Eigenen Abfragen Suche schlecht beschriftete Bilder mit Eigenen Abfragen Ist die Bilderdatenbank über einen längeren Zeitraum in Benutzung, so steigt die Wahrscheinlichkeit für schlecht beschriftete Bilder 1. Insbesondere

Mehr

Windows Presentation Foundation (WPF) -Grundlagen -Steuerelemente. Dr. Beatrice Amrhein

Windows Presentation Foundation (WPF) -Grundlagen -Steuerelemente. Dr. Beatrice Amrhein Windows Presentation Foundation (WPF) -Grundlagen -Steuerelemente Dr. Beatrice Amrhein Überblick Die Architektur WPF Projekt erstellen Steuerelemente einfügen Eigenschaften von Steuerelementen ändern Nach

Mehr

Source Code Konverter... 2. Online: (VB.net <-> C#)... 3. Kommerzielle Produkte (VB, C#, C++, Java)... 3. Code Nachbearbeitung in der Praxis...

Source Code Konverter... 2. Online: (VB.net <-> C#)... 3. Kommerzielle Produkte (VB, C#, C++, Java)... 3. Code Nachbearbeitung in der Praxis... Autor: Thomas Reinwart 2008-05-05 office@reinwart.com Inhalt Source Code Konverter... 2 Online: (VB.net C#)... 3 Kommerzielle Produkte (VB, C#, C++, Java)... 3 Code Nachbearbeitung in der Praxis...

Mehr

TTS - TinyTimeSystem. Unterrichtsprojekt BIBI

TTS - TinyTimeSystem. Unterrichtsprojekt BIBI TTS - TinyTimeSystem Unterrichtsprojekt BIBI Mathias Metzler, Philipp Winder, Viktor Sohm 28.01.2008 TinyTimeSystem Inhaltsverzeichnis Problemstellung... 2 Lösungsvorschlag... 2 Punkte die unser Tool erfüllen

Mehr

Objektorientierte Programmierung für Anfänger am Beispiel PHP

Objektorientierte Programmierung für Anfänger am Beispiel PHP Objektorientierte Programmierung für Anfänger am Beispiel PHP Johannes Mittendorfer http://jmittendorfer.hostingsociety.com 19. August 2012 Abstract Dieses Dokument soll die Vorteile der objektorientierten

Mehr

Objektorientierte Programmierung. Kapitel 12: Interfaces

Objektorientierte Programmierung. Kapitel 12: Interfaces 12. Interfaces 1/14 Objektorientierte Programmierung Kapitel 12: Interfaces Stefan Brass Martin-Luther-Universität Halle-Wittenberg Wintersemester 2012/13 http://www.informatik.uni-halle.de/ brass/oop12/

Mehr

Vererbung & Schnittstellen in C#

Vererbung & Schnittstellen in C# Vererbung & Schnittstellen in C# Inhaltsübersicht - Vorüberlegung - Vererbung - Schnittstellenklassen - Zusammenfassung 1 Vorüberlegung Wozu benötigt man Vererbung überhaubt? 1.Um Zeit zu sparen! Verwendung

Mehr

Starthilfe für C# Inhaltsverzeichnis. Medien- und Kommunikationsinformatik (B.Sc.) Alexander Paharukov. Informatik 3 Praktikum

Starthilfe für C# Inhaltsverzeichnis. Medien- und Kommunikationsinformatik (B.Sc.) Alexander Paharukov. Informatik 3 Praktikum Starthilfe für C# Inhaltsverzeichnis Allgemeines... 2 Bezugsquellen... 2 SharpDevelop... 2.NET Runtime... 2.NET SDK... 2 Installation... 2 Reihenfolge... 2 Vorschlag für eine Ordnerstruktur... 3 Arbeit

Mehr

C# im Vergleich zu Java

C# im Vergleich zu Java C# im Vergleich zu Java Serhad Ilgün Seminar Universität Dortmund SS 03 Gliederung Entstehung von C# und Java Überblick von C# und Java Unterschiede und Gemeinsamkeiten Zusammenfassung und Ausblick Entstehung

Mehr

Anleitung zum Arbeiten mit Microsoft Visual Studio 2008 im Softwarepraktikum ET/IT

Anleitung zum Arbeiten mit Microsoft Visual Studio 2008 im Softwarepraktikum ET/IT Boris Golubovic Dortmund, den 24. Oktober 2010 Anleitung zum Arbeiten mit Microsoft Visual Studio 2008 im Softwarepraktikum ET/IT Ein Projekt anlegen Ein Projekt kapselt alle zu einer Anwendung gehörenden

Mehr

Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge

Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge Ab der Version forma 5.5 handelt es sich bei den Orientierungshilfen der Architekten-/Objektplanerverträge nicht

Mehr

Prinzipien Objektorientierter Programmierung

Prinzipien Objektorientierter Programmierung Prinzipien Objektorientierter Programmierung Valerian Wintner Inhaltsverzeichnis 1 Vorwort 1 2 Kapselung 1 3 Polymorphie 2 3.1 Dynamische Polymorphie...................... 2 3.2 Statische Polymorphie........................

Mehr

Diese Ansicht erhalten Sie nach der erfolgreichen Anmeldung bei Wordpress.

Diese Ansicht erhalten Sie nach der erfolgreichen Anmeldung bei Wordpress. Anmeldung http://www.ihredomain.de/wp-admin Dashboard Diese Ansicht erhalten Sie nach der erfolgreichen Anmeldung bei Wordpress. Das Dashboard gibt Ihnen eine kurze Übersicht, z.b. Anzahl der Beiträge,

Mehr

Vorkurs C++ Programmierung

Vorkurs C++ Programmierung Vorkurs C++ Programmierung Klassen Letzte Stunde Speicherverwaltung automatische Speicherverwaltung auf dem Stack dynamische Speicherverwaltung auf dem Heap new/new[] und delete/delete[] Speicherklassen:

Mehr

Step by Step Webserver unter Windows Server 2003. von Christian Bartl

Step by Step Webserver unter Windows Server 2003. von Christian Bartl Step by Step Webserver unter Windows Server 2003 von Webserver unter Windows Server 2003 Um den WWW-Server-Dienst IIS (Internet Information Service) zu nutzen muss dieser zunächst installiert werden (wird

Mehr

Verhindert, dass eine Methode überschrieben wird. public final int holekontostand() {...} public final class Girokonto extends Konto {...

Verhindert, dass eine Methode überschrieben wird. public final int holekontostand() {...} public final class Girokonto extends Konto {... PIWIN I Kap. 8 Objektorientierte Programmierung - Vererbung 31 Schlüsselwort: final Verhindert, dass eine Methode überschrieben wird public final int holekontostand() {... Erben von einer Klasse verbieten:

Mehr

Zentrale Installation

Zentrale Installation Einführung STEP 7 wird durch ein Setup-Programm installiert. Eingabeaufforderungen auf dem Bildschirm führen Sie Schritt für Schritt durch den gesamten Installationsvorgang. Mit der Record-Funktion steht

Mehr

Softwaretests in Visual Studio 2010 Ultimate Vergleich mit Java-Testwerkzeugen. Alexander Schunk Marcel Teuber Henry Trobisch

Softwaretests in Visual Studio 2010 Ultimate Vergleich mit Java-Testwerkzeugen. Alexander Schunk Marcel Teuber Henry Trobisch Softwaretests in Visual Studio 2010 Ultimate Vergleich mit Java-Testwerkzeugen Alexander Schunk Henry Trobisch Inhalt 1. Vergleich der Unit-Tests... 2 2. Vergleich der Codeabdeckungs-Tests... 2 3. Vergleich

Mehr

Die Dateiablage Der Weg zur Dateiablage

Die Dateiablage Der Weg zur Dateiablage Die Dateiablage In Ihrem Privatbereich haben Sie die Möglichkeit, Dateien verschiedener Formate abzulegen, zu sortieren, zu archivieren und in andere Dateiablagen der Plattform zu kopieren. In den Gruppen

Mehr

Leitfaden zur ersten Nutzung der R FOM Portable-Version für Windows (Version 1.0)

Leitfaden zur ersten Nutzung der R FOM Portable-Version für Windows (Version 1.0) Leitfaden zur ersten Nutzung der R FOM Portable-Version für Windows (Version 1.0) Peter Koos 03. Dezember 2015 0 Inhaltsverzeichnis 1 Voraussetzung... 3 2 Hintergrundinformationen... 3 2.1 Installationsarten...

Mehr

Faktura. IT.S FAIR Faktura. Handbuch. Dauner Str.12, D-41236 Mönchengladbach, Hotline: 0900/1 296 607 (1,30 /Min)

Faktura. IT.S FAIR Faktura. Handbuch. Dauner Str.12, D-41236 Mönchengladbach, Hotline: 0900/1 296 607 (1,30 /Min) IT.S FAIR Faktura Handbuch Dauner Str.12, D-41236 Mönchengladbach, Hotline: 0900/1 296 607 (1,30 /Min) 1. Inhalt 1. Inhalt... 2 2. Wie lege ich einen Kontakt an?... 3 3. Wie erstelle ich eine Aktion für

Mehr

Windows Server 2012 R2 Essentials & Hyper-V

Windows Server 2012 R2 Essentials & Hyper-V erklärt: Windows Server 2012 R2 Essentials & Hyper-V Windows Server 2012 R2 Essentials bietet gegenüber der Vorgängerversion die Möglichkeit, mit den Boardmitteln den Windows Server 2012 R2 Essentials

Mehr

3. Auflage. O Reillys Taschenbibliothek. C# 5.0 kurz & gut. Joseph Albahari & Ben Albahari O REILLY. Aktualisierung von Lars Schulten

3. Auflage. O Reillys Taschenbibliothek. C# 5.0 kurz & gut. Joseph Albahari & Ben Albahari O REILLY. Aktualisierung von Lars Schulten O Reillys Taschenbibliothek 3. Auflage C# 5.0 kurz & gut O REILLY Joseph Albahari & Ben Albahari Aktualisierung von Lars Schulten Inhalt C# 5.0 kurz & gut... 1 Ein erstes C#-Programm... 2 Syntax... 5 Typgrundlagen...

Mehr

Bauteilattribute als Sachdaten anzeigen

Bauteilattribute als Sachdaten anzeigen Mit den speedikon Attributfiltern können Sie die speedikon Attribute eines Bauteils als MicroStation Sachdaten an die Elemente anhängen Inhalte Was ist ein speedikon Attribut?... 3 Eigene Attribute vergeben...

Mehr

PowerPoint 2010 Mit Folienmastern arbeiten

PowerPoint 2010 Mit Folienmastern arbeiten PP.002, Version 1.1 07.04.2015 Kurzanleitung PowerPoint 2010 Mit Folienmastern arbeiten Der Folienmaster ist die Vorlage für sämtliche Folien einer Präsentation. Er bestimmt das Design, die Farben, die

Mehr

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf http://informatik.swoke.de. Seite 1 von 22

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf http://informatik.swoke.de. Seite 1 von 22 Kapitel 19 Vererbung, UML Seite 1 von 22 Vererbung - Neben der Datenabstraktion und der Datenkapselung ist die Vererbung ein weiteres Merkmal der OOP. - Durch Vererbung werden die Methoden und die Eigenschaften

Mehr

Hex Datei mit Atmel Studio 6 erstellen

Hex Datei mit Atmel Studio 6 erstellen Hex Datei mit Atmel Studio 6 erstellen Es werden generell keine Atmel Studio Dateien ins Repository geladen, da jeder seine Dateien an anderen Orten liegen hat und weil nicht jeder das Atmel Studio 6 benutzt.

Mehr

PHP Kurs Online Kurs Analysten Programmierer Web PHP

PHP Kurs Online Kurs Analysten Programmierer Web PHP PHP Kurs Online Kurs Analysten Programmierer Web PHP Akademie Domani info@akademiedomani.de Allgemeines Programm des Kurses PHP Modul 1 - Einführung und Installation PHP-Umgebung Erste Lerneinheit Introduzione

Mehr

Programmieren in Java

Programmieren in Java Programmieren in Java objektorientierte Programmierung 2 2 Zusammenhang Klasse-Datei In jeder *.java Datei kann es genau eine public-klasse geben wobei Klassen- und Dateiname übereinstimmen. Es können

Mehr

ARAkoll 2013 Dokumentation. Datum: 21.11.2012

ARAkoll 2013 Dokumentation. Datum: 21.11.2012 ARAkoll 2013 Dokumentation Datum: 21.11.2012 INHALT Allgemeines... 3 Funktionsübersicht... 3 Allgemeine Funktionen... 3 ARAmatic Symbolleiste... 3 Monatsprotokoll erzeugen... 4 Jahresprotokoll erzeugen

Mehr

Einrichten einer Festplatte mit FDISK unter Windows 95/98/98SE/Me

Einrichten einer Festplatte mit FDISK unter Windows 95/98/98SE/Me Einrichten einer Festplatte mit FDISK unter Windows 95/98/98SE/Me Bevor Sie die Platte zum ersten Mal benutzen können, muss sie noch partitioniert und formatiert werden! Vorher zeigt sich die Festplatte

Mehr

Version 0.3. Installation von MinGW und Eclipse CDT

Version 0.3. Installation von MinGW und Eclipse CDT Version 0.3 Installation von MinGW und Eclipse CDT 1. Stellen Sie fest, ob Sie Windows in der 32 Bit Version oder in der 64 Bit Version installiert haben. 2. Prüfen Sie, welche Java Runtime vorhanden ist.

Mehr

5 DATEN. 5.1. Variablen. Variablen können beliebige Werte zugewiesen und im Gegensatz zu

5 DATEN. 5.1. Variablen. Variablen können beliebige Werte zugewiesen und im Gegensatz zu Daten Makro + VBA effektiv 5 DATEN 5.1. Variablen Variablen können beliebige Werte zugewiesen und im Gegensatz zu Konstanten jederzeit im Programm verändert werden. Als Variablen können beliebige Zeichenketten

Mehr

Arbeiten mit UMLed und Delphi

Arbeiten mit UMLed und Delphi Arbeiten mit UMLed und Delphi Diese Anleitung soll zeigen, wie man Klassen mit dem UML ( Unified Modeling Language ) Editor UMLed erstellt, in Delphi exportiert und dort so einbindet, dass diese (bis auf

Mehr

Programmierkurs Java

Programmierkurs Java Programmierkurs Java Dr. Dietrich Boles Aufgaben zu UE16-Rekursion (Stand 09.12.2011) Aufgabe 1: Implementieren Sie in Java ein Programm, das solange einzelne Zeichen vom Terminal einliest, bis ein #-Zeichen

Mehr

Javadoc. Programmiermethodik. Eva Zangerle Universität Innsbruck

Javadoc. Programmiermethodik. Eva Zangerle Universität Innsbruck Javadoc Programmiermethodik Eva Zangerle Universität Innsbruck Überblick Einführung Java Ein erster Überblick Objektorientierung Vererbung und Polymorphismus Ausnahmebehandlung Pakete und Javadoc Spezielle

Mehr

DOKUMENTATION VOGELZUCHT 2015 PLUS

DOKUMENTATION VOGELZUCHT 2015 PLUS DOKUMENTATION VOGELZUCHT 2015 PLUS Vogelzucht2015 App für Geräte mit Android Betriebssystemen Läuft nur in Zusammenhang mit einer Vollversion vogelzucht2015 auf einem PC. Zusammenfassung: a. Mit der APP

Mehr

4D Server v12 64-bit Version BETA VERSION

4D Server v12 64-bit Version BETA VERSION 4D Server v12 64-bit Version BETA VERSION 4D Server v12 unterstützt jetzt das Windows 64-bit Betriebssystem. Hauptvorteil der 64-bit Technologie ist die rundum verbesserte Performance der Anwendungen und

Mehr

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java: Technische Informatik für Ingenieure (TIfI) WS 2005/2006, Vorlesung 9 II. Grundlagen der Programmierung Ekkart Kindler Funktionen und Prozeduren Datenstrukturen 9. Datenstrukturen Daten zusammenfassen

Mehr

Handbuch ECDL 2003 Basic Modul 5: Datenbank Grundlagen von relationalen Datenbanken

Handbuch ECDL 2003 Basic Modul 5: Datenbank Grundlagen von relationalen Datenbanken Handbuch ECDL 2003 Basic Modul 5: Datenbank Grundlagen von relationalen Datenbanken Dateiname: ecdl5_01_00_documentation_standard.doc Speicherdatum: 14.02.2005 ECDL 2003 Basic Modul 5 Datenbank - Grundlagen

Mehr

Sichern der persönlichen Daten auf einem Windows Computer

Sichern der persönlichen Daten auf einem Windows Computer Sichern der persönlichen Daten auf einem Windows Computer DIRECTION DES SERVICES IT SERVICE DIT-MI DIREKTION DER IT-DIENSTE DIENSTSTELLE DIT-MI 1/9 1 Inhaltsverzeichnis 2 Einleitung... 3 3 Outlook Daten...

Mehr

Artikel Schnittstelle über CSV

Artikel Schnittstelle über CSV Artikel Schnittstelle über CSV Sie können Artikeldaten aus Ihrem EDV System in das NCFOX importieren, dies geschieht durch eine CSV Schnittstelle. Dies hat mehrere Vorteile: Zeitersparnis, die Karteikarte

Mehr

S TAND N OVEMBE R 2012 HANDBUCH DUDLE.ELK-WUE.DE T E R M I N A B S P R A C H E N I N D E R L A N D E S K I R C H E

S TAND N OVEMBE R 2012 HANDBUCH DUDLE.ELK-WUE.DE T E R M I N A B S P R A C H E N I N D E R L A N D E S K I R C H E S TAND N OVEMBE R 2012 HANDBUCH T E R M I N A B S P R A C H E N I N D E R L A N D E S K I R C H E Herausgeber Referat Informationstechnologie in der Landeskirche und im Oberkirchenrat Evangelischer Oberkirchenrat

Mehr

SafeRun-Modus: Die Sichere Umgebung für die Ausführung von Programmen

SafeRun-Modus: Die Sichere Umgebung für die Ausführung von Programmen SafeRun-Modus: Die Sichere Umgebung für die Ausführung von Programmen Um die maximale Sicherheit für das Betriebssystem und Ihre persönlichen Daten zu gewährleisten, können Sie Programme von Drittherstellern

Mehr

Einrichtung des Cisco VPN Clients (IPSEC) in Windows7

Einrichtung des Cisco VPN Clients (IPSEC) in Windows7 Einrichtung des Cisco VPN Clients (IPSEC) in Windows7 Diese Verbindung muss einmalig eingerichtet werden und wird benötigt, um den Zugriff vom privaten Rechner oder der Workstation im Home Office über

Mehr

Klassenentwurf. Wie schreiben wir Klassen, die leicht zu verstehen, wartbar und wiederverwendbar sind? Objektorientierte Programmierung mit Java

Klassenentwurf. Wie schreiben wir Klassen, die leicht zu verstehen, wartbar und wiederverwendbar sind? Objektorientierte Programmierung mit Java Objektorientierte Programmierung mit Java Eine praxisnahe Einführung mit BlueJ Klassenentwurf Wie schreiben wir Klassen, die leicht zu verstehen, wartbar und wiederverwendbar sind? 1.0 Zentrale Konzepte

Mehr

Einführung zum Arbeiten mit Microsoft Visual C++ 2010 Express Edition

Einführung zum Arbeiten mit Microsoft Visual C++ 2010 Express Edition In den nachfolgenden Schritten finden Sie beschrieben, wie Sie in der Entwicklungsumgebung Microsoft Visual Studio 2010 eine Projektmappe, ein Projekt und einen ersten Quellcode erstellen, diesen kompilieren,

Mehr

VBA-Programmierung: Zusammenfassung

VBA-Programmierung: Zusammenfassung VBA-Programmierung: Zusammenfassung Programmiersprachen (Definition, Einordnung VBA) Softwareentwicklung-Phasen: 1. Spezifikation 2. Entwurf 3. Implementierung Datentypen (einfach, zusammengesetzt) Programmablaufsteuerung

Mehr

Einrichten des IIS für VDF WebApp. Einrichten des IIS (Internet Information Server) zur Verwendung von Visual DataFlex Web Applications

Einrichten des IIS für VDF WebApp. Einrichten des IIS (Internet Information Server) zur Verwendung von Visual DataFlex Web Applications Einrichten des IIS (Internet Information Server) zur Verwendung von Visual DataFlex Web Applications Windows 8 Systemsteuerung > Programme > Windows Features aktivieren / deaktivieren > Im Verzeichnisbaum

Mehr

CL-Mini-ABF. Kurzbeschreibung. Installation und Vorbereitung. Stand 30.01.2012. Ihre HTK-Filiale Michelstadt

CL-Mini-ABF. Kurzbeschreibung. Installation und Vorbereitung. Stand 30.01.2012. Ihre HTK-Filiale Michelstadt 64720 email : Info@KM-EDV.de Stand 30.01.2012 CL-Mini-ABF Inhaltsverzeichnis Kurzbeschreibung... 1 Installation und Vorbereitung...1 ODBC-Zugriff... 2 ODBC-Einrichtung unter Windows XP...2 ODBC-Einrichtung

Mehr

Einführung in Eclipse und Java

Einführung in Eclipse und Java Universität Bayreuth Lehrstuhl für Angewandte Informatik IV Datenbanken und Informationssysteme Prof. Dr.-Ing. Jablonski Einführung in Eclipse und Java Dipl.Inf. Manuel Götz Lehrstuhl für Angewandte Informatik

Mehr

Wie halte ich Ordnung auf meiner Festplatte?

Wie halte ich Ordnung auf meiner Festplatte? Wie halte ich Ordnung auf meiner Festplatte? Was hältst du von folgender Ordnung? Du hast zu Hause einen Schrank. Alles was dir im Wege ist, Zeitungen, Briefe, schmutzige Wäsche, Essensreste, Küchenabfälle,

Mehr

VB.net Programmierung und Beispielprogramm für GSV

VB.net Programmierung und Beispielprogramm für GSV VB.net Programmierung und Beispielprogramm für GSV Dokumentation Stand vom 26.05.2011 Tel +49 (0)3302 78620 60, Fax +49 (0)3302 78620 69, info@me-systeme.de, www.me-systeme.de 1 Inhaltsverzeichnis Vorwort...2

Mehr

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen Binäre Bäume 1. Allgemeines Binäre Bäume werden grundsätzlich verwendet, um Zahlen der Größe nach, oder Wörter dem Alphabet nach zu sortieren. Dem einfacheren Verständnis zu Liebe werde ich mich hier besonders

Mehr

Inhalt. 1 Einleitung AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER

Inhalt. 1 Einleitung AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER Inhalt 1 Einleitung... 1 2 Einrichtung der Aufgabe für die automatische Sicherung... 2 2.1 Die Aufgabenplanung... 2 2.2 Der erste Testlauf... 9 3 Problembehebung...

Mehr

32.4 Anpassen von Menüs und Symbolleisten 795i

32.4 Anpassen von Menüs und Symbolleisten 795i 32.4 Anpassen von Menüs und Symbolleisten 795i Fortsetzung der Seiten in der 8. Auflage 32.4 Anpassen von Menüs und Symbolleisten 32.4.1 Anpassen von Menüs Die Menüs können um folgende Typen von Optionen

Mehr

How To: Wie entwickle ich mit SharpDevelop Anwendungen für die PocketPC-Platform

How To: Wie entwickle ich mit SharpDevelop Anwendungen für die PocketPC-Platform How To: Wie entwickle ich mit SharpDevelop Anwendungen für die PocketPC-Platform 0. Benötigt werden folgende Softwarepakete:.NET Framework Software Development Kit (http://www.microsoft.com/downloads/details.aspx?familyid=4fe5bdb5-c7a7-4505-9927-2213868a325b&displaylang=en)

Mehr

Lizenzen auschecken. Was ist zu tun?

Lizenzen auschecken. Was ist zu tun? Use case Lizenzen auschecken Ihr Unternehmen hat eine Netzwerk-Commuterlizenz mit beispielsweise 4 Lizenzen. Am Freitag wollen Sie Ihren Laptop mit nach Hause nehmen, um dort am Wochenende weiter zu arbeiten.

Mehr

1 Vom Problem zum Programm

1 Vom Problem zum Programm Hintergrundinformationen zur Vorlesung GRUNDLAGEN DER INFORMATIK I Studiengang Elektrotechnik WS 02/03 AG Betriebssysteme FB3 Kirsten Berkenkötter 1 Vom Problem zum Programm Aufgabenstellung analysieren

Mehr

Lokale Installation von DotNetNuke 4 ohne IIS

Lokale Installation von DotNetNuke 4 ohne IIS Lokale Installation von DotNetNuke 4 ohne IIS ITM GmbH Wankelstr. 14 70563 Stuttgart http://www.itm-consulting.de Benjamin Hermann hermann@itm-consulting.de 12.12.2006 Agenda Benötigte Komponenten Installation

Mehr

Python SVN-Revision 12

Python SVN-Revision 12 Python SVN-Revision 12 Uwe Ziegenhagen 7. Januar 2012 Vorwort Dieses Skript erhebt keinen Anspruch auf Vollständigkeit oder Richtigkeit. Es wird geschrieben, um mir als Gedächtnisstütze für den Umgang

Mehr

Einführung in das Microsoft.NET-Framework. Programmiersprache C# 02: Visual Studio / Hello World. Boris Hülsmann

Einführung in das Microsoft.NET-Framework. Programmiersprache C# 02: Visual Studio / Hello World. Boris Hülsmann Einführung in das Microsoft.NET-Framework Programmiersprache C# 02: Visual Studio / Hello World Boris Hülsmann 23.09.2010 1 In dieser Einführung bekommen Sie einen kurzen Einstieg in das.net-framework

Mehr

Software-Engineering und Optimierungsanwendungen in der Thermodynamik

Software-Engineering und Optimierungsanwendungen in der Thermodynamik Software-Engineering und Optimierungsanwendungen in der Thermodynamik Software-Engineering 5 Programmentwicklung und Debuggen mit IDE und CASE-Tools Übungen Prof. Dr. Rolf Dornberger OPTSWE_SWE: 5 Programmentwicklung

Mehr

Technische Dokumentation SilentStatistikTool

Technische Dokumentation SilentStatistikTool Technische Dokumentation SilentStatistikTool Version 1.0 Marko Schröder 1115063 Inhalt Einleitung... 3 Klasse Program... 3 Klasse ArgumentHandler... 3 Bereitgestellte Variablen... 3 Bereitgestellte Methoden...

Mehr

Die Erstellung eigener Strukturprofile

Die Erstellung eigener Strukturprofile Die Erstellung eigener Strukturprofile Manchmal ist es nötig, eigene Profile zu Erstellen, die man dann mittels Gestellgenerator verbaut. Diese Strukturprofile werden in einer Benutzerbezogenen Bibliothek

Mehr

Wo hat mein Computer meine Dateien schon wieder versteckt? Tipps und Tricks Dateien wieder zu finden.

Wo hat mein Computer meine Dateien schon wieder versteckt? Tipps und Tricks Dateien wieder zu finden. Wo hat mein Computer meine Dateien schon wieder versteckt? Tipps und Tricks Dateien wieder zu finden. 1 Die Hauptordner der verschiedenen Windows- Systeme Von Ordnern und Unterordnern Neuer Ordner erstellen

Mehr

virtuos Leitfaden für die virtuelle Lehre

virtuos Leitfaden für die virtuelle Lehre virtuos Zentrum zur Unterstützung virtueller Lehre der Universität Osnabrück virtuos Leitfaden für die virtuelle Lehre Zentrum virtuos Tel: 0541-969-6501 Email: kursmanager@uni-osnabrueck.de URL: www.virtuos.uni-osnabrueck.de

Mehr

SEP 114. Design by Contract

SEP 114. Design by Contract Design by Contract SEP 114 Design by Contract Teile das zu entwickelnde Programm in kleine Einheiten (Klassen, Methoden), die unabhängig voneinander entwickelt und überprüft werden können. Einheiten mit

Mehr

In 12 Schritten zum mobilen PC mit Paragon Drive Copy 11 und Microsoft Windows Virtual PC

In 12 Schritten zum mobilen PC mit Paragon Drive Copy 11 und Microsoft Windows Virtual PC PARAGON Technologie GmbH, Systemprogrammierung Heinrich-von-Stephan-Str. 5c 79100 Freiburg, Germany Tel. +49 (0) 761 59018201 Fax +49 (0) 761 59018130 Internet www.paragon-software.com Email sales@paragon-software.com

Mehr

Objektorientierte Programmierung

Objektorientierte Programmierung Objektorientierte Programmierung 1 Geschichte Dahl, Nygaard: Simula 67 (Algol 60 + Objektorientierung) Kay et al.: Smalltalk (erste rein-objektorientierte Sprache) Object Pascal, Objective C, C++ (wiederum

Mehr

MORE Profile. Pass- und Lizenzverwaltungssystem. Stand: 19.02.2014 MORE Projects GmbH

MORE Profile. Pass- und Lizenzverwaltungssystem. Stand: 19.02.2014 MORE Projects GmbH MORE Profile Pass- und Lizenzverwaltungssystem erstellt von: Thorsten Schumann erreichbar unter: thorsten.schumann@more-projects.de Stand: MORE Projects GmbH Einführung Die in More Profile integrierte

Mehr

Installation einer C++ Entwicklungsumgebung unter Windows --- TDM-GCC und Eclipse installieren

Installation einer C++ Entwicklungsumgebung unter Windows --- TDM-GCC und Eclipse installieren Installation einer C++ Entwicklungsumgebung unter Windows --- TDM-GCC und Eclipse installieren 1 32- oder 64-bit Windows feststellen In den nachfolgenden Schritten ist es nötig, dass Sie wissen, ob Sie

Mehr

Die Beschreibung bezieht sich auf die Version Dreamweaver 4.0. In der Version MX ist die Sitedefinition leicht geändert worden.

Die Beschreibung bezieht sich auf die Version Dreamweaver 4.0. In der Version MX ist die Sitedefinition leicht geändert worden. In einer Website haben Seiten oft das gleiche Layout. Speziell beim Einsatz von Tabellen, in denen die Navigation auf der linken oder rechten Seite, oben oder unten eingesetzt wird. Diese Anteile der Website

Mehr

Tutorium Rechnerorganisation

Tutorium Rechnerorganisation Woche 2 Tutorien 3 und 4 zur Vorlesung Rechnerorganisation 1 Christian A. Mandery: KIT Universität des Landes Baden-Württemberg und nationales Grossforschungszentrum in der Helmholtz-Gemeinschaft www.kit.edu

Mehr

MailUtilities: Remote Deployment - Einführung

MailUtilities: Remote Deployment - Einführung MailUtilities: Remote Deployment - Einführung Zielsetzung Die Aufgabe von Remote Deployment adressiert zwei Szenarien: 1. Konfiguration der MailUtilities von einer Workstation aus, damit man das Control

Mehr

Grundlagen von Python

Grundlagen von Python Einführung in Python Grundlagen von Python Felix Döring, Felix Wittwer November 17, 2015 Scriptcharakter Programmierparadigmen Imperatives Programmieren Das Scoping Problem Objektorientiertes Programmieren

Mehr

Web-Kürzel. Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter

Web-Kürzel. Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter 2 Inhaltsverzeichnis 1 Web-Kürzel 4 1.1 Einführung.......................................... 4 1.2 Web-Kürzel.........................................

Mehr

Der Kalender im ipad

Der Kalender im ipad Der Kalender im ipad Wir haben im ipad, dem ipod Touch und dem iphone, sowie auf dem PC in der Cloud einen Kalender. Die App ist voreingestellt, man braucht sie nicht laden. So macht es das ipad leicht,

Mehr

Hilfe zur Dokumentenverwaltung

Hilfe zur Dokumentenverwaltung Hilfe zur Dokumentenverwaltung Die Dokumentenverwaltung von Coffee-CRM ist sehr mächtig und umfangreich, aber keine Angst die Bedienung ist kinderleicht. Im Gegensatz zur Foto Galeria können Dokumente

Mehr

Durchführung der Datenübernahme nach Reisekosten 2011

Durchführung der Datenübernahme nach Reisekosten 2011 Durchführung der Datenübernahme nach Reisekosten 2011 1. Starten Sie QuickSteuer Deluxe 2010. Rufen Sie anschließend über den Menüpunkt /Extras/Reisekosten Rechner den QuickSteuer Deluxe 2010 Reisekosten-Rechner,

Mehr

Einführung in die Informatik Tools

Einführung in die Informatik Tools Einführung in die Informatik Tools Werkzeuge zur Erstellung von Softwareprojekten Wolfram Burgard 8.1 Motivation Große Softwareprojekte werden schnell unübersichtlich. Änderungen im Code können leicht

Mehr

Installation SQL- Server 2012 Single Node

Installation SQL- Server 2012 Single Node Installation SQL- Server 2012 Single Node Dies ist eine Installationsanleitung für den neuen SQL Server 2012. Es beschreibt eine Single Node Installation auf einem virtuellen Windows Server 2008 R2 mit

Mehr

Installation und Inbetriebnahme von SolidWorks

Installation und Inbetriebnahme von SolidWorks Inhaltsverzeichnis FAKULTÄT FÜR INGENIEURWISSENSCHAFTEN I Prof. Dr.-Ing. Frank Lobeck Installation und Inbetriebnahme von SolidWorks Inhaltsverzeichnis Inhaltsverzeichnis... I 1. Einleitung... 1 2. Installation...

Mehr

Klausur WS 2006/07 Programmiersprache Java Objektorientierte Programmierung II 15. März 2007

Klausur WS 2006/07 Programmiersprache Java Objektorientierte Programmierung II 15. März 2007 Fachhochschule Bonn-Rhein-Sieg University of Applied Sciences Fachbereich Informatik Prof. Dr. Peter Becker Klausur WS 2006/07 Programmiersprache Java Objektorientierte Programmierung II 15. März 2007

Mehr

Handbuch B4000+ Preset Manager

Handbuch B4000+ Preset Manager Handbuch B4000+ Preset Manager B4000+ authentic organ modeller Version 0.6 FERROFISH advanced audio applications Einleitung Mit der Software B4000+ Preset Manager können Sie Ihre in der B4000+ erstellten

Mehr

1. Aktionen-Palette durch "Fenster /Aktionen ALT+F9" öffnen. 2. Anlegen eines neuen Set über "Neues Set..." (über das kleine Dreieck zu erreichen)

1. Aktionen-Palette durch Fenster /Aktionen ALT+F9 öffnen. 2. Anlegen eines neuen Set über Neues Set... (über das kleine Dreieck zu erreichen) Tipp: Aktionen (c) 2005 Thomas Stölting, Stand: 25.4. 2005 In Photoshop werden häufig immer wieder die gleichen Befehlssequenzen benötigt. Um sie nicht jedesmal manuell neu eingeben zu müssen, können diese

Mehr

Anleitung zur Daten zur Datensicherung und Datenrücksicherung. Datensicherung

Anleitung zur Daten zur Datensicherung und Datenrücksicherung. Datensicherung Anleitung zur Daten zur Datensicherung und Datenrücksicherung Datensicherung Es gibt drei Möglichkeiten der Datensicherung. Zwei davon sind in Ges eingebaut, die dritte ist eine manuelle Möglichkeit. In

Mehr

Im Folgenden wird Ihnen an einem Beispiel erklärt, wie Sie Excel-Anlagen und Excel-Vorlagen erstellen können.

Im Folgenden wird Ihnen an einem Beispiel erklärt, wie Sie Excel-Anlagen und Excel-Vorlagen erstellen können. Excel-Schnittstelle Im Folgenden wird Ihnen an einem Beispiel erklärt, wie Sie Excel-Anlagen und Excel-Vorlagen erstellen können. Voraussetzung: Microsoft Office Excel ab Version 2000 Zum verwendeten Beispiel:

Mehr

E-Mail-Versand an Galileo Kundenstamm. Galileo / Outlook

E-Mail-Versand an Galileo Kundenstamm. Galileo / Outlook E-Mail-Versand an Galileo Kundenstamm Galileo / Outlook 1 Grundsätzliches...1 2 Voraussetzung...1 3 Vorbereitung...2 3.1 E-Mail-Adressen exportieren 2 3.1.1 Ohne Filter 2 3.1.2 Mit Filter 2 4 Mail-Versand

Mehr

mobilepoi 0.91 Demo Version Anleitung Das Software Studio Christian Efinger Erstellt am 21. Oktober 2005

mobilepoi 0.91 Demo Version Anleitung Das Software Studio Christian Efinger Erstellt am 21. Oktober 2005 Das Software Studio Christian Efinger mobilepoi 0.91 Demo Version Anleitung Erstellt am 21. Oktober 2005 Kontakt: Das Software Studio Christian Efinger ce@efinger-online.de Inhalt 1. Einführung... 3 2.

Mehr

Java Kurs für Anfänger Einheit 5 Methoden

Java Kurs für Anfänger Einheit 5 Methoden Java Kurs für Anfänger Einheit 5 Methoden Ludwig-Maximilians-Universität München (Institut für Informatik: Programmierung und Softwaretechnik von Prof.Wirsing) 22. Juni 2009 Inhaltsverzeichnis Methoden

Mehr

Bedienungsanleitung. Stand: 26.05.2011. Copyright 2011 by GEVITAS GmbH www.gevitas.de

Bedienungsanleitung. Stand: 26.05.2011. Copyright 2011 by GEVITAS GmbH www.gevitas.de GEVITAS-Sync Bedienungsanleitung Stand: 26.05.2011 Copyright 2011 by GEVITAS GmbH www.gevitas.de Inhalt 1. Einleitung... 3 1.1. Installation... 3 1.2. Zugriffsrechte... 3 1.3. Starten... 4 1.4. Die Menü-Leiste...

Mehr

12. Dokumente Speichern und Drucken

12. Dokumente Speichern und Drucken 12. Dokumente Speichern und Drucken 12.1 Überblick Wie oft sollte man sein Dokument speichern? Nachdem Sie ein Word Dokument erstellt oder bearbeitet haben, sollten Sie es immer speichern. Sie sollten

Mehr

TELIS FINANZ Login App

TELIS FINANZ Login App Installation & Bedienung der TELIS FINANZ Login App 1. Voraussetzungen - Android Version 4.0 oder höher - Uhrzeit automatisch gestellt - Für die Einrichtung wird einmalig eine Internetverbindung benötigt

Mehr

Dokumentation von Ük Modul 302

Dokumentation von Ük Modul 302 Dokumentation von Ük Modul 302 Von Nicolas Kull Seite 1/ Inhaltsverzeichnis Dokumentation von Ük Modul 302... 1 Inhaltsverzeichnis... 2 Abbildungsverzeichnis... 3 Typographie (Layout)... 4 Schrift... 4

Mehr