Visual C# Grundlagen, Programmiertechniken, Datenbanken. Frank Eller. An imprint of Pearson Education

Relevanta dokument
Logik für Informatiker

Metallmaßstäbe RL. Inhaltsverzeichnis

TYSKA, KORT LÄROKURS, skriftlig del

Mycket formellt, mottagaren har en speciell titel som ska användas i stället för namnet

Nachrichten auf Deutsch

ARBETSBLAD. KORTFILMSKLUBBEN TYSKA Bamboule

ARBETSBLAD KORTFILMSKLUBBEN TYSKA. Durch die Blumen (lätt) Ordkunskap Välj ut 10 av orden/fraserna nedan och sätt ihop en dialog på tyska!

301 Tage, Deutschland

301 Tage, Deutschland

Aspekte zur Character Semantik

Türkisch für Anfänger

Akademiker Öppning. Öppning - Introduktion. I denna uppsats kommer jag att undersöka/utreda/utvärdera/analysera...

Nachrichten auf Deutsch

Ich bin der Jens ich bin der Jens Jansen ich bin hier der Vater der Familie von Mette, Gesa, Helge, Sonja und jetzt auch von Sofi.

Hallo und herzlich willkommen zu Unsere Hitliste! Ich bin Niklas, und hier sind meine vier Freunde...

BÄTTRE ÄN NÅGONSIN. Bäste medarbetare

Einstufungstest Välkomna! Aufgabenblätter

Grammatikübungsbuch Schwedisch

PPV-Serie. DIN Axialkolben Verstellpumpe für LKW Nebenabtrieb mit Load Sensing-Regler. Erstinbetriebnahme: Saugstutzen muß separat bestellt werden

Leroy. Teil 1. A R B E T S B L A D PROGRAMNR / tv1

Bewerbung Anschreiben

Nachrichten auf Deutsch 09. April 2011

Välkomna! Einstufungstest. Aufgabenblätter

Hej! God morgon! Tjänare! Hejsan! 1 Hej!

2. Setz die passende Verbform ein! (2 Punkte pro richtige Form!) / 16

301 Tage, Deutschland

Mr. Adam Smith Smith Plastics 8 Crossfield Road Selly Oak Birmingham West Midlands B29 1WQ

Mr. Adam Smith Smith's Plastics 8 Crossfield Road Selly Oak Birmingham West Midlands B29 1WQ

0/22. Proseminar Programmiersysteme WS 2003/04. Typklassen: Haskell. Mark Kaminski. Betreuer: Andreas Rossberg. 1. April 2004

TYSKA. Türkisch für Anfänger. Teil 5. Diese Arbeitsblätter gibt es:

SERVICEINSTRUKTION Tider. SERVICE INSTRUCTION Times. Zeiten SIT SE/GB/DE M10401 FIGHTER 2005/2010

Resa Logi Logi - Hitta boende Svenska Tyska Wo kann ich finden? ... ein Zimmer zu vermieten? ... ein Hostel? ... ein Hotel?

Resa Logi Logi - Hitta boende Tyska Svenska Var hittar jag? ... ett rum att hyra? ... ett vandrarhem? ... ett hotell? ... ett bed-and-breakfast?

Nachrichten auf Deutsch 12. März 2011

Ich glaube, ich schreibe meistens über Figuren oder Personen, die gerade Schwierigkeiten in ihrem Leben haben, also die am Kämpfen sind.

Veranda. DE Installationshandbuch V17/16

TYSKA. Mango, das Zebra. Baby-Tiere. Diese Arbeitsblätter gibt es: 1. Vokabeln zur Sendung 2. Aufgaben zur Sendung 3. Lösungen ARBETSBLAD 2007/08

Kan jag ta ut pengar i [land] utan att behöva betala extra avgifter? Fragen, ob Gebühren anfallen, wenn man in einem bestimmten Land Geld abhebt

Var kan jag hitta formuläret för? Var kan jag hitta formuläret för? Fragen wo man ein Formular findet

TYSKA. Türkisch für Anfänger. Teil 6. Diese Arbeitsblätter gibt es:

Fußball und Skate. Eliteschule - Training - trainieren - Sport - Verein - Fußballerin - laufen - skaten - schwimmen - Fahrrad fahren

TYSKA, KORT LÄROKURS

4.2 Konstantes Fördervolumen Doppelpume

TYSKA. Türkisch für Anfänger. Teil 3. Diese Arbeitsblätter gibt es:

SchwedenQuiz. Quiz & Spiele. Diese Arbeitsblätter gibt es: 1. Vokabeln zur Sendung 2. Was weißt du über Schweden? (frågeformulär) 3.

Türkisch für Anfänger

Vi hoppas att du ser fram emot att lära dig ännu mera tyska. För att det ska gå så bra som möjligt får du här några tips från oss.

Ja, es ist ein Platz, wo oft Veranstaltungen sind, das heißt, man kann sich hier mit Freunden treffen...

Optioner Options Optionen

SERVICEINSTRUKTION Värmeproduktion. SERVICE INSTRUCTION Heat production. Wärmeerzeugung SIT SE/GB/DE M10383 FIGHTER 1320

Kulturminnesvårdens perifera organisation Bergstrand, Axel Fornvännen 1939(34), s

Ansökan Följebrev. Följebrev - Inledning. Formellt, manlig mottagare, namnet okänt. Formellt, kvinnlig mottagare, namnet okänt

Prävention alkoholbedingter Jugendgewalt (PAJ) Radioprojekt Webgeflüster

Nachrichten auf Deutsch

In Ringen und Werffen können nachvolgende \ück nützlich gebraucht werden, deren seindt achtzehen

F1220, F1230, F1120, F1130

301 Tage, Deutschland

WiLlk. VÄLKo. WiLlkommen. VÄLkOMMEN

Eine haarige Verwandlung

4 Fritid. 1 De tycker om att gå på restaurang. a Skriv under bilderna! Schreiben Sie unter die Bilder: Was machen die Personen?

Jonathan Hedlund heter jag, är 20 år och jobbar här i Zürich som au pair för tre killar.

4. Dialogövning Läroplanen säger: Olika former av samtal, dialoger och intervjuer.

Deutsche Hits. Diese Arbeitsblätter gibt es:

Buske Sprachkalender SCHWEDISCH 2016

Jurtor-by på JUVENGÅRD

Schweiz kvinnlig rösträtt

Ich rufe Sie morgen um zehn an!

Immigration Bostad. Bostad - Hyra. Ange att du vill hyra någonting. ein Zimmer Typ av bostad. eine Wohnung/ ein Apartment Typ av bostad.

Studieanvisning för Att kommunicera på tyska. Kurskod: 715G26. Hp: 7,5. Ht 2017

Reisen Unterwegs. Unterwegs - Ort. Jag har gått vilse. Du weißt nicht, wo Du bist

Zum ersten Mal gelesen zu werden ist so ein Gefühl, als würde man splitternackt durch die Stadt laufen

Gebrauchsanweisung. Bure. Gehwagen. Bure XL

PER MAUSKLICK zur Eigenheimfinanzierung

WALLMEK i Kungälv AB Special tools for auto repairs

Sveriges överenskommelser med främmande makter

CTC Rumsdisplay CTC Roomdisplay Installations- och skötselanvisning. Installation and maintenance instructions

Tala: die Schule und der Stundenplan. Skriva: kennen lernen (träna perfekt) Drama: Levon lernt Svetlana kennen

Musik für jede Laune. Sag s mir!

Lagrange-Projektion. LMU München, Germany Thomas Schöps. Hüttenseminar im Zillertal bei Prof. Lars Diening Wintersemester 2014/2015

Mein Berlin Levon Mitt Berlin Levon

K j on unkti ktioner

301 Tage, Deutschland

Rajd Instruction. Svenska Deutsch English

Deutsche Grammatik, Achte Klasse

Välkommen till arbetsbladet som hjälper dig att förstå och arbeta med den andra episoden i serien Bankrånet!

Geschäftskorrespondenz

Lektion. 1Hej! Vad heter du? Sprachkurs Schwedisch, Buch 2012 Hueber Verlag, Ismaning, ISBN

HANDPUMP H-11 DIRECTIONS FOR USE BRUKSANVISNING GEBRAUCHANWEISUNG

Deutsch lernen und lehren I, 3 högskolepoäng

Und täglich grüßt das Murmeltier Min dag som murmel Einleitung Lektion 16: Und täglich grüßt das Murmeltier... 2

Personligt Brev. Brev - Adress. Herrn Peter Müller Falkenstraße Hamburg Deutschland

Personligt Brev. Brev - Adress. Mr. N. Summerbee Tyres of Manhattan 335 Main Street New York NY 92926

TYSKA. Überraschungsparty! Feste & Feiern. Diese Arbeitsblätter gibt es:

HTML5. Leitfaden für Webentwickler. Klaus Förster, Bernd Öggl. An imprint of Pearson Education

S in Stockholm, Göteborg, Malmö und Lund. Neue Regelungen

Tariff Kit. Installatörshandbok Tariff Kit för NIBE F1330 LEK. Installer manual Tariff Kit for NIBE F1330

Seminar Rough Sets. Präsentation von Christian Köllner Betreuer: Philipp Bender. Wintersemester 2003 / 04

Resa Äta ute. Äta ute - Vid entrén. Äta ute - Beställa mat

Resa Äta ute. Äta ute - Vid entrén. Äta ute - Beställa mat

REFERENCE. The scope of work included the prefabrication and installation of: - Copal aluminium and glass balcony railings 400 rm

Transkript:

Frank Eller Visual C# 2010 Grundlagen, Programmiertechniken, Datenbanken An imprint of Pearson Education München Boston San Francisco Harlow, England Don Mills, Ontario Sydney Mexico City Madrid Amsterdam

Kapitel 12 Generics SortedDictionary<K, V> ähnelt dem Dictionary, ist aber sortiert. Das Sortierkriterium ist dabei der Schlüssel. SortedList<K, V> ähnelt dem SortedDictionary. Auch hierbei handelt es sich um eine Liste aus Schlüssel-Werte-Paaren, die nach dem Schlüssel sortiert sind. HashSet<T> ist eine generische Collection, die für Operationen auf sogenannte»sets«vorgesehen ist. Als Set wird eine Collection bezeichnet, die keine doppelten Elemente beinhaltet. Eine Sortierung ist bei einem HashSet nicht vorgesehen, die hohe Geschwindigkeit wird dadurch erreicht, dass die Klasse mit Hashcodes arbeitet. SynchronizedCollection<T> ist eine threadsichere Collection, die intern mit einer List<T> arbeitet. Aus der oberen Tabelle lässt sich erkennen, dass SortedDictionary<K, V> und SortedList<K, V> offenbar die gleiche Art der Implementierung besitzen. In der Tat repräsentieren beide intern einen binären Suchbaum, durch den die Elemente schnell gefunden werden können. Sie unterscheiden sich jedoch in einigen Punkten: SortedDictionary<K, V> benötigt mehr Speicher als SortedList<K, V>. SortedList<K, V> ist schneller gefüllt, wenn alle Elemente auf einen Schlag und vorsortiert eingefügt werden. SortedDictionary<K, V> ist schneller beim Einfügen und Entnehmen, wenn die Werte noch nicht sortiert sind. 12.6.2 Zusätzliche Methoden generischer Listenklassen Die Verwendung generischer Klassen haben Sie bereits kennengelernt, und die generischen Listenklassen machen da keine Ausnahme sie lassen sich auf die gleiche Art verwenden. Allerdings besitzen sie im Vergleich zu den herkömmlichen Listenarten, die Sie in Kapitel 11 kennengelernt haben, einige weitere interessante Methoden. Diese tragen mitunter zur Vereinfachung des Codes bei, können aber bei übermäßigem Gebrauch auch zu Verwirrung führen. Sortieren mittels Comparison<T> Die Sort()-Methode funktioniert auch bei generischen Listen wie gewohnt. Sofern das in der Liste enthaltene Element das Interface IComparable implementiert (wobei die generische Variante bevorzugt verwendet werden sollte), wird die Liste entsprechend sortiert. Das Gleiche gilt für die Sortierung mittels IComparer bzw. IComparer<T>. Generische Listen bieten allerdings noch eine dritte Variante an, bei der die Sort()-Methode ein Element vom Typ Comparison<T> erwartet. Comparison<T> ist ein Delegate, der wie folgt aufgebaut ist: public delegate int Comparison<T>( T value1, T value2 ); Er erwartet zwei Parameter vom Typ T (T ist ja über die Liste bereits vorgegeben) und liefert einen int- Wert zurück, der sich genauso verhält wie bei den Vergleichsmethoden CompareTo() bzw. Compare() der 394

Covarianz und Contravarianz Interface IComparable und IComparer. Comparison<T> ermöglicht es also, zusätzlich zu möglicherweise eingebauten Sortiervarianten weitere Sortierungen vorzunehmen. Die Methode TrueForAll() TrueForAll() ermöglicht es zu kontrollieren, ob eine bestimmte Bedingung für alle Elemente einer Liste gilt. Dazu erwartet die Methode wiederum einen Delegate, diesmal vom Typ Predicate<T>. Predicate<T> ist folgendermaßen aufgebaut: public delegate bool Predicate<T>( T item ); Der Delegate erwartet ein Element vom Typ T (wiederum ist T bereits über die Liste festgelegt). Innerhalb der Delegate-Methode erfolgt dann die Kontrolle auf die gewünschte Bedingung, deren Gültigkeit für alle Elemente überprüft werden soll. TrueForAll() durchläuft alle Elemente der Liste und ruft für jedes Element den Delegate auf, das Gesamtresultat wird zurückgeliefert. Auf diese Weise können Sie kontrollieren, ob eine bestimmte Bedingung für alle Elemente der Liste gültig ist. Die Methode ForEach() ForEach() funktioniert generell wie eine foreach-schleife, allerdings wiederum mit einem Delegate. Für jedes Element der Liste wird eine bestimmte Aktion durchgeführt, die mithilfe eines Delegates vom Typ Action<T> angegeben wird. Action<T> ist wie folgt deklariert: public delegate void Action<T>( T item ); Die angegebene Methode wird für jedes Element der Liste durchgeführt, das ist auch schon alles. Bei all diesen Methoden, die Delegates verwenden, ist es auch häufig der Fall, dass direkt mithilfe anonymer Methoden programmiert wird. Sofern die entsprechende Methode nicht viel Code enthält, ist dagegen generell nichts einzuwenden. Bei viel Code in einer anonymen Methode sollten Sie aber überlegen, ob Sie nicht wirklich eine eigene Methode schreiben. Anonyme Methoden haben einen großen Nachteil vor allem bei der Fehlersuche. Da eine anonyme Methode de facto nicht existiert und vom Compiler in eine»herkömmliche«methode umgewandelt wird, gibt es ein großes Problem, wenn innerhalb der anonymen Methode ein Fehler auftritt. In diesem Fall stimmen nämlich die Zeilennummern des Quellcodes und des kompilierten Codes nicht mehr überein (zwangsläufig). Das bedeutet, bei einem Fehler innerhalb einer anonymen Methode bekommen Sie im Visual Studio nicht den korrekten Ort des Fehlers angezeigt. HINWEIS 12.7 Covarianz und Contravarianz Covarianz und Contravarianz sind ein Feature, das neu ist im.net Framework 4.0. Der Oberbegriff, der beide Varianten beschreibt, ist Varianz Die wichtigsten Interfaces (derzeit funktioniert dieses Feature nur mit Interfaces und Delegates) sind im.net Framework 4.0 mit Varianz ausgestattet. Varianz bringt noch mehr Flexibilität im Falle generischer Interfaces und Delegates, weil sie etwas ermöglicht, was bisher nicht möglich war: die Verwendung von Klassenhierarchien in generischen Typparametern. Am besten werden Covarianz und Contravarianz anhand eines kleinen Beispiels deutlich. 395

Kapitel 12 Generics 12.7.1 Covarianz in Interfaces Es ist immer mit Schwierigkeiten verbunden, ein Beispiel möglichst einfach, aber dennoch realitätsrelevant zu halten. In diesem Fall hat die Einfachheit gesiegt und der Realitätsbezug ein klein wenig gelitten. Ziel des Beispiels ist allerdings nur, dass Sie Covarianz verstehen. Vorbereitungen Varianz hat mit Vererbung zu tun, daher benötigen wir zunächst eine Klassenhierarchie. Diese wird aussehen wie in Abbildung 12.6 gezeigt. Abbildung 12.6: Die Klassenhierarchie der Applikation DVD Sie finden den gesamten Quelltext des Beispielprogramms auf der beiliegenden DVD im Verzeichnis <DVD-ROM>\Buchdaten\Beispiele\<Version>\Kapitel_12\CovarianceSample. Basisklasse ist die Klasse Person, von der wiederum FemalePerson und MalePerson abgeleitet sind. Beide implementieren das generische Interface IOutput, das die Implementierung der Methode Output() erzwingt. Listing 12.14 zeigt zunächst die Deklaration der Basisklasse Person, die nicht weiter schwierig ist, besteht sie doch nur aus zwei Eigenschaften und der Methode ToString(). public class Person public string LastName get; set; 396

Covarianz und Contravarianz public string FirstName get; set; public override string ToString() return String.Format( "Das ist Person 0 1", FirstName, LastName ); Listing 12.14: Die Basisklasse Person für das Beispielprogramm Die abgeleiteten Klassen implementieren das Interface IOutput<T>. Das muss daher zuerst deklariert werden. Es erzwingt aber nur eine einzige Methode und ist daher ebenfalls sehr einfach aufgebaut, wie Listing 12.15 zeigt. public interface IOutput<T> void Output(); Listing 12.15: Das Interface IOutput<T> Natürlich ist auch dem Autor klar, dass hier keineswegs ein generisches Interface benötigt würde auch ohne Verwendung von Generics würde alles wie vorgesehen funktionieren. Allerdings lässt sich ohne Generics auch keine Varianz erklären, daher handelt es sich um ein generisches Interface. Die Klassen MalePerson und FemalePerson implementieren jeweils ihre Version des Interface, also einmal IOutput<FemalePerson> und einmal IOutput<MalePerson>. Listing 12.16 zeigt den Code für die beiden Klassen. public class FemalePerson : Person, IOutput<FemalePerson> public override string ToString() return String.Format( "Frau 0 1", FirstName, LastName ); #region IOutput<FemalePerson> Members void IOutput<FemalePerson>.Output() Console.WriteLine( ToString() + " ist eine Frau" ); #endregion public class MalePerson : Person, IOutput<MalePerson> public override string ToString() return String.Format( "Herr 0 1", FirstName, LastName ); 397

Kapitel 12 Generics #region IOutput<MalePerson> Members void IOutput<MalePerson>.Output() Console.WriteLine( ToString() + " ist ein Mann" ); #endregion Listing 12.16: Die Klassen FemalePerson und MalePerson Damit sind die Vorbereitungen für das Beispiel bereits abgeschlossen, und wir können uns an das Hauptprogramm machen. Das Hauptprogramm Im Hauptprogramm sollen einige Objekte vom Typ FemalePerson und MalePerson erzeugt und zu einer Liste hinzugefügt werden. Dann soll diese Liste ausgegeben werden, allerdings nicht auf herkömmliche Art, sondern ausschließlich über die Methode Output() des Interface IOutput<T>. Das Befüllen der Liste ist noch recht einfach, weil hier (bei den Klassen) die Polymorphie greift. Das bedeutet, eine Liste vom Typ List<Person> kann sowohl Objekte vom Typ MalePerson als auch Objekte vom Typ FemalePerson aufnehmen. Zu Problemen kommt es erst bei der Ausgabe, denn hier ist es notwendig, in das Interface zu casten. Wie Sie am Code der Klassen MalePerson und FemalePerson sehen können, sind die Interfaces explizit implementiert, was das Casten nötig macht. Zunächst aber der Code zum Füllen der Liste in Listing 12.17. class Program private static Random _randomizer = new Random(); private static string[] _lastnames = "Meier", "Müller", "Kurz", "Lang", "Hinz", "Kunz", "Schmidt", "Pfeifer", "Becker" ; private static string[] _femalenames = "Adelheid", "Berta", "Cinderella", "Diana", "Else", "Frauke", "Gerda", "Heike" ; private static string[] _malenames = "Adam", "Bert", "Charly", "Dagobert", "Ernst", "Frank", "Gerd", "Hans" ; private static FemalePerson CreateFemalePerson() string lastname = _lastnames[_randomizer.next( _lastnames.length )]; string firstname = _femalenames[_randomizer.next( _femalenames.length )]; return new FemalePerson() FirstName = firstname, LastName = lastname ; private static MalePerson CreateMaleItem() string lastname = _lastnames[_randomizer.next( _lastnames.length )]; string firstname = _malenames[_randomizer.next( _malenames.length )]; 398

Covarianz und Contravarianz return new MalePerson() FirstName = firstname, LastName = lastname ; static void Main( string[] args ) List<Person> people = new List<Person>(); for ( int i=0; i < 5; i++ ) people.add( CreateFemalePerson() ); people.add( CreateMaleItem() ); // An dieser Stelle folgt die Ausgabe... Listing 12.17: Erzeugen und Befüllen der Liste Als Programmierer würden Sie an dieser Stelle vermutlich zu dem durchaus logischen Schluss kommen, dass Sie zwei Möglichkeiten haben. Entweder Sie kontrollieren jedes Mal, welches Interface implementiert ist, oder Sie verwenden das Interface IOutput<Person> und casten in dieses. Sollte ja kein Problem sein, Polymorphie macht es möglich. Oder auch nicht. Es wird nämlich nicht funktionieren, stattdessen bekommen Sie eine Fehlermeldung, eine NullReferenceException. Die Konvertierung ist fehlgeschlagen. Nur warum? Zunächst der Code, um das Ganze deutlicher zu machen (Listing 12.18). static void Main( string[] args ) List<Person> people = new List<Person>(); for ( int i=0; i < 5; i++ ) people.add( CreateFemalePerson() ); people.add( CreateMaleItem() ); foreach ( var x in people ) (x as IOutput<Person>).Output(); Listing 12.18: Diese Variante der Methode Main() liefert den Fehler. Die Konvertierung nach IOutput<Person> schlägt fehl. Aus dieser Fehlermeldung folgt, dass Polymorphie bei Interfaces offensichtlich nicht funktioniert. Hat sie in der Tat noch nie, IOutput<MalePerson> kann nicht automatisch nach IOutput<Person> umgewandelt werden. Und das ist jetzt der Punkt, an dem wir zum ur- 399

Kapitel 12 Generics sprünglichen Thema zurückkommen, zur Covarianz. Mit.NET 4.0 geht es nämlich doch, allerdings müssen Sie dem Interface erst mitteilen, dass eine derartige Umwandlung möglich sein soll. Das funktioniert über das Schlüsselwort out, das vor den Typparameter geschrieben werden muss. Der Code des Interface muss wie in Listing 12.19 gezeigt abgeändert werden. public interface IOutput<out T> void Output(); Listing 12.19: Das abgeänderte Interface, jetzt zu Covarianz fähig Das Ergebnis sehen Sie, wenn Sie das Programm starten jetzt funktioniert es nämlich. Abbildung 12.7 zeigt den Screenshot. Abbildung 12.7: Das funktionierende Programm 12.7.2 Covarianz in Kürze Das Beispielprogramm war in der Tat recht umfangreich, und was hier genau geschieht, lässt sich auch kürzer erklären. Es geht dabei schlicht um die Zuweisung eines generischen Interface, bei der der Typparameter automatisch konvertiert werden soll. Genau das ist mit.net vor 4.0 bzw. ohne das Schlüsselwort out vor dem generischen Parameter nicht möglich. Unter Verwendung der gleichen Klassen sähe das Ganze dann so aus wie in Listing 12.20. static void Main( string[] args ) IOutput<MalePerson> imale = CreateMaleItem(); IOutput<Person> iperson = imale; // geht nicht ohne "out". Listing 12.20: Zuweisung von IOutput<MalePerson> an IOutput<Person> Wenn das Interface IOutput<T> nicht covariant ist (also das Schlüsselwort out fehlt), kommt es zu einer Fehlermeldung, die besagt, dass eine derartige Konvertierung nicht möglich ist. Wenn Sie das Schlüsselwort hinschreiben, funktioniert alles tadellos. 400

Covarianz und Contravarianz 12.7.3 Contravarianz Contravarianz wird in der Hauptsache bei generischen Delegates eine Rolle spielen, weshalb diese Möglichkeit auch hier in einem Beispielprogramm aufgegriffen wird. Wieder zeigt der Code zunächst die nicht funktionierende Variante und dann die benötigte Änderung. Sie finden den gesamten Quelltext des Beispielprogramms auf der beiliegenden DVD im Verzeichnis <DVD-ROM>\Buchdaten\Beispiele\<Version>\Kapitel_12\CovarianceSample. DVD Vorbereitungen Wieder werden mehrere Klassen benötigt. Der Einfachheit halber finden wieder die Klassen Person, FemalePerson und MalePerson Verwendung, mit leichten Änderungen im Vergleich zum vorangegangenen Beispiel. Listing 12.21 zeigt den Code der Klassen Person, MalePerson und FemalePerson. public class Person private bool _isfemale = false; public string LastName get; set; public string FirstName get; set; public bool IsFemale get return this._isfemale; protected set this._isfemale = value; public override string ToString() return "ToString()-Aufruf in Person"; public class MalePerson : Person 401

Kapitel 12 Generics public override string ToString() return String.Format( "Herr 0 1", FirstName, LastName ); public MalePerson() this.isfemale = false; public class FemalePerson : Person public override string ToString() return String.Format( "Frau 0 1", FirstName, LastName ); public FemalePerson() this.isfemale = true; Listing 12.21: Die Klassen Person, MalePerson und FemalePerson Des Weiteren wird ein generischer Delegate benötigt. In diesem Fall soll dieser dazu dienen, etwas auszugeben. Das Einzige, was innerhalb des Beispiels ausgegeben werden kann, ist vermutlich der zurückgelieferte Wert von ToString() der Klassen MalePerson und FemalePerson. Der Delegate wird daher generisch deklariert, und das folgendermaßen: public delegate void OutputHandler<T>( T item ); Damit wären die Vorbereitungen auch schon abgeschlossen, und es kann an das Hauptprogramm gehen. Das Hauptprogramm Das Hauptprogramm besteht zunächst wieder aus den bereits bekannten Methoden zum Erzeugen von Instanzen der Klassen FemalePerson und MalePerson. Diese wurden aus dem Vorgängerbeispiel übernommen und sind daher nicht erneut abgedruckt. Zusätzlich benötigen wir aber auch noch eine Ausgabemethode, die später mithilfe des deklarierten Delegates angesprochen werden soll. Diese ist sehr einfach aufgebaut, wie Listing 12.22 zeigt. class Program [... ] private static void Output( Person p ) 402

Covarianz und Contravarianz Console.WriteLine(p.ToString()); [... ] Listing 12.22: Die Methode für die Ausgabe Die Ausgabemethode ist direkt in Program deklariert und könnte demnach auch direkt angesprochen werden. Das ist jedoch nicht immer der Fall, es gibt Situationen, da müssen Sie Methodenaufrufe über Delegates durchführen, weil die wirkliche Methode möglicherweise an einer ganz anderen Stelle deklariert ist. Beachten Sie, dass die Beispiele immer wesentlich einfacher aufgebaut sind, als das in der Realität vorkommen wird. HINWEIS Der Aufruf soll über Delegates erfolgen. Diese werden nun zunächst zugewiesen. Danach erfolgen die Erzeugung der Liste und der Aufruf der Ausgabemethode (via Delegate). An dieser Stelle ist es sinnvoll, da ja beide Ausgaben mit der gleichen Methode durchgeführt werden, einfach einen allgemeinen Delegate (mit dem generischen Typparameter Person) zu deklarieren und diesen dann den spezialisierten Delegates zuzuweisen. Genau dort liegt aber auch das Problem, denn diese Zuweisung ist unzulässig. Das bestimmt auch irgendwo die Logik, die aus den objektorientierten Konzepten folgt. Wenn eine direkte Zuweisung einer Variablen des Typs FemalePerson an eine Variable des Typs Person unzulässig ist, muss das auch mit entsprechenden Delegates so sein. In Wirklichkeit sollte es allerdings möglich sein, diese Zuweisung vorzunehmen, auch vom logischen Standpunkt aus. Bei genauer Betrachtung kommen wir zu folgendem Ergebnis: Der allgemeine Delegate ist definiert als Output<Person>. Das bedeutet nichts anderes, als dass der Methode, die dem Delegate zugewiesen wird, eine Variable vom Typ Person übergeben wird. Würde dem Delegate Output<Person> nun ein Delegate Output<FemalePerson> zugewiesen, wäre das vom logischen Standpunkt aus korrekt, denn es bedeutet lediglich, dass nun statt einer Variablen vom Typ Person eben eine Variable vom Typ FemalePerson übergeben wird. Das ist dank Polymorphie erlaubt. Es sollte also möglich sein. Sie können sich leicht davon überzeugen, dass eine derartige Zuweisung nicht funktioniert. Listing 12.23 zeigt den Code der Methode Main(), der wie gesagt aktuell nicht funktioniert. Sie können ihn dennoch abtippen, ähnlich wie beim vorangegangenen Beispiel ist auch hier nur eine geringfügige Änderung nötig, um die Funktionalität herzustellen. class Program [... ] static void Main( string[] args ) OutputHandler<Person> outhandler = Output; 403

Copyright Daten, Texte, Design und Grafiken dieses ebooks, sowie die eventuell angebotenen ebook-zusatzdaten sind urheberrechtlich geschützt. Dieses ebook stellen wir lediglich als persönliche Einzelplatz-Lizenz zur Verfügung! Jede andere Verwendung dieses ebooks oder zugehöriger Materialien und Informationen, einschliesslich der Reproduktion, der Weitergabe, des Weitervertriebs, der Platzierung im Internet, in Intranets, in Extranets, der Veränderung, des Weiterverkaufs und der Veröffentlichung bedarf der schriftlichen Genehmigung des Verlags. Insbesondere ist die Entfernung oder Änderung des vom Verlag vergebenen Passwortschutzes ausdrücklich untersagt! Bei Fragen zu diesem Thema wenden Sie sich bitte an: info@pearson.de Zusatzdaten Möglicherweise liegt dem gedruckten Buch eine CD-ROM mit Zusatzdaten bei. Die Zurverfügungstellung dieser Daten auf unseren Websites ist eine freiwillige Leistung des Verlags. Der Rechtsweg ist ausgeschlossen. Hinweis Dieses und viele weitere ebooks können Sie rund um die Uhr und legal auf unserer Website http://www.informit.de herunterladen