Visual C# 2012 Grundkurs

Generics

Testen Sie unsere 2012 Kurse

10 Tage kostenlos!

Jetzt testen Alle Abonnements anzeigen
Die Erstellung eines Type-Parameters, welcher über den gesamten Kontext der Klasse wie ein Datentyp verwendet werden kann, ermöglicht es, diesen erst zum Zeitpunkt der Benutzung einer generischen Klasse definieren zu müssen.

Transkript

In diesem Abschnitt stelle ich eine ganz wunderbare Sache der Sprache C# vor und zwar "Generics". Ich möchte mal mit einem Programmbeispiel beginnen, mit einem Szenario, das relativ häufig vorkommt. Man braucht ja häufig sogenannte "Factory Methods". Also ich habe da irgendeine Klasse, die dient mir jetzt mal als Factory-Klasse. So eine Factory-Method, die hat meistens das Wort "Create" in sich. "Public object create element", und jetzt kann ich nach irgendwelchen Kriterien so eine Auswertung machen. Irgendwann an einem Punkt kann ich ein Objekt von einem bestimmten Typ anlegen. Dann bekomme ich dieses Objekt hier zurück. Legen wir mal eine Testklasse an, um das ganze Beispiel ein wenig klarer zu machen. Machen wir mal diese "Class" "Mitarbeiter". Hier hat es irgendwelche Felder und "Properties". Jetzt kann ich hier z.B. "Return new Mitarbeiter" schreiben, wenn in diesen "Criteria" irgendwie herauskommt, dass ich eben einen Mitarbeiter anlegen soll. Jetzt, im aufrufenden Kontext, lege ich also so eine Factory mal an, "factoryf=newfactory", und dann kann ich sagen: "Mitarbeiterm=", und jetzt muss ich irgendwie so eine Konversion hier machen, "Mitarbeiterf.CreateElement" und gebe da irgendwelche Kriterien mit rein. Und nun kann ich mit diesem Mitarbeiter irgendetwas machen. Das ist alles recht und schön, aber es geht eleganter und zwar indem ich jetzt diese Factory zu einer generischen Klasse mache. Hier kann ich jetzt in spitzen Klammern einen sogenannten Type-Parameter reinschreiben. Und jetzt kann ich sozusagen dieses T im gesamten Kontext der Klasse verwenden, wie einen Datentyp. Und es wäre zum Beispiel, ich könnte sagen, diese Methode "Create Element" könnte ein "T" zurückgeben und jetzt wäre es natürlich schön, wenn ich jetzt hier "New T" zurückgeben könnte. Aber das scheint aus irgendeinem Grund nicht zu gehen. Wir werden uns gleich noch damit beschäftigen warum das nicht geht und eine Lösung dafür finden. Aber im Augenblick möchte ich jetzt einmal Folgendes zeigen es gibt in .NET diese Klasse "Activator". Diese Klasse hat eine Methode "Create Instance" und diese "Create Instance" kann uns nun ein Objekt erzeugen. Und um unser Szenario fertig zu stellen, benutze ich dieses "Create Instance", um ein Element vom Typ "T" zu erzeugen. Das kann an der Stelle natürlich nur dann funktionieren, wenn T ein Typ ist, der über ein "Default Constructor" verfügt. Davon gehen wir jetzt einfach mal in dem Moment aus. Was ich zeigen möchte ist, dass ich hier diesen generischen Parameter "T" verwenden kann wie einen normalen Datentypen. Ich kann hier konvertieren in "T" und ich kann auch das Schlüsselwort "Typeof" verwenden, das ja ein Objekt vom Typ "System.Type" zurückgibt, das dann diesen Datentypen repräsentiert. Weil das mit diesem generischen Typen "T" auch funktioniert, kann ich eben "Create Instance" hier aufrufen, ohne im Augenblick zu wissen, was "T" denn letztendlich sein wird. Im aufrufenden Kontext, der kann jetzt festlegen, was "T" sein soll. In dem Fall sage ich jetzt "Factory von Mitarbeiter" ist gleich "New Factory von Mitarbeiter". Jetzt weiß die Factory, dass sie "Mitarbeiter" erzeugen soll, und jetzt brauche ich hier an der Stelle auch überhaupt keine Konvertierung mehr. "Create Element", das ist völlig klar, IntelliSense zeigt es mir an, dass "Create Element" jetzt hier eine Mitarbeiter zurückzugeben hat. Soweit so gut. Ich kann jetzt hier den Code kompilieren. Sie sehen der Compiler macht das. Wenn ich den ausführe passiert nichts, insofern sparen wir uns das "Ausführen". Jetzt stellt sich die Frage, warum konnte ich vorhin hier an der Stelle nicht einfach schreiben "New T". Schauen wir uns noch einmal die Meldung an, die uns der Compiler angibt. "Cannot create an instance of the variable T because it does not have the new constrain". Das schöne nun an diesen "Generics" ist, dass hier in der Klassendefinition ein paar Angaben darüber machen kann, was man von diesem Typ erwarten kann. Solche Angaben nennen sich "Constraints". So ein Constraint beginnt immer mit dem Schlüsselwort RER und dem Namen des generischen Parameters. Und jetzt kann ich hier nach dem Doppelpunkt irgendetwas hinschreiben, was dieser Typ ist. Eine der Sachen, die man hier hinschreiben kann, ist zum Beispiel "New". Und dass bedeutet jetzt der generische Typ T verfügt über einen Constructor, also einen Constructor ohne Parameter. Der Compiler ist an der Stelle jetzt schon wieder happy. Und jetzt kann ich eben dieses "New T" verwenden. Ich kann aber auch Folgendes machen: Ich kann sagen: "Word T" ist "Object". Es ist natürlich so, dass man jetzt wiederum nicht weiß: Hat dieses Objekt einen "Default Constructor", ja oder nein? Das bringt uns an der Stelle nicht sehr viel weiter. Aber es gibt ja in .NET auch noch so diese Interface-Typen. Ich könnte also jetzt hier so ein Interface deklarieren, könnte ich z.B. so irgendetwas machen. Ich kann an der Stelle also jetzt z.B. sagen, dass T ein "ITest" sein soll und ich kann die Liste verlängern, indem ich jetzt z.B. auch noch einmal sage, T soll einen "Default Constructor" haben. Dann kann ich T also jetzt hier erzeugen. Ich kann aber an irgendeiner anderen Stelle hier, "voidf", ich mache mal hier gerade irgend so eine Methode, und ich kann jetzt hier irgendwie so ein Objekt "T" anlegen. Und da ich jetzt weiß, dass "T" vom Interface "I-Test ist, weiß ich auch, dass "T" eine Methode "Foo" hat. Die kann ich an der Stelle aufrufen. -"Generics" lassen uns mit unbekannten Typen arbeiten. Für jeden dieser unbekannten Typen, mit denen ich arbeiten möchte, muss ich so einen generischen Parameter anlegen. Ich kann mehrere solcher generischer Typen deklarieren und kann die dann innerhalb der Klasse verwenden und aufrufen im Kontext. Da, wo ich so eine Klasse erstelle, da sage ich dann erst, was dieser Typ "T" jetzt tatsächlich sein soll. In dem Fall müsste ich jetzt den "Mitarbeiter" von "I-Test"-- Müsste ich dieses "I-Test" implementieren, und ich bräuchte auch eine Methode "Foo", damit der Compiler es zulässt, dass wir diese Factory hier überhaupt mit diesen "Mitarbeitern" benutzen. Wenn eine dieser Sachen fehlt ich maskiere das noch mal raus dann sagt mir der Compiler, dass das nicht funktioniert, weil der Typ "Mitarbeiter" diesen Constraint für diesen generischen Typ nicht genügt. Das Anwendungsgebiet mit den sich die Generics im .NET eingeführt haben, dass waren die Collection Klassen und kommen mit einem reichhaltigen Set an Collection für die verschiedensten Zwecke, die eben alle auf dies generische Art und Weise implementiert worden sind. In meinem Fall könnte ich hier dieses Pattern, dass ich hier mit diesem Typ T eingeführt habe: "T:New". Ich nehme dieses Constraint mit dem Interface wieder heraus und auch diese Methode. Ich könnte dieses Pattern sehr leicht zu so einer Art Persistenzmechanismus umbauen. Dann würde das Ganze "Persistenzmanager" z.B. heißen. Dann könnte ich irgendwelche Objekte nach bestimmten Kriterien abfragen. Diese "Criteria" kann jetzt irgendeinen "String" sein, der etwas enthält oder was ja auch noch geht, es könnte ein "Delegate" sein oder ein "Expression Tree" also Dinge mit denen ich Funktionalität übergeben kann, die dann wiederum aus dem aufgerufenen Kontext stammen. Belassen wir es hier bei diesem "String". Ich kann diesen "String" hier umwandeln. Zum Beispiel in ein "Sql Statement". Ich kann Daten abrufen. Ich kann ein Objekt vom Typ "T" erzeugen. Ich kann dieses Objekt mit Daten füllen und kann es am Ende zurückgeben und dann könnte ich hier ein Persistenzmanager anlegen. Kann hier eine "Query" aufrufen und erhalte dann aus dieser "Query" ein Mitarbeiterobjekt und könnte mit diesem Mitarbeiterobjekt irgendetwas machen. Das war in diesem Abschnitt einen Abriss über die "Generics" in .NET.

Visual C# 2012 Grundkurs

Schreiben Sie eigene Programme in C# und lernen Sie dazu alle Schlüsselwörter und die meisten Konstrukte kennen, um sicher mit dieser Programmierspreche umzugehen.

7 Std. 1 min (44 Videos)
Derzeit sind keine Feedbacks vorhanden...
 

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!