Generics. FirstLeft. 4.0 Einführung. 4.1 Entscheiden, wann und wo Generics verwendet werden sollten. Max. Linie. Max. Linie KAPITEL 4.

Größe: px
Ab Seite anzeigen:

Download "Generics. FirstLeft. 4.0 Einführung. 4.1 Entscheiden, wann und wo Generics verwendet werden sollten. Max. Linie. Max. Linie KAPITEL 4."

Transkript

1 FirstLeft. Kapitel 4 KAPITEL 4 Generics 4.0 Einführung Ein lang erwartetes Feature, Generics, hat mit Version 2.0 des C#-Compilers endlich Einzug gehalten. Generics sind ein ausgesprochen nützliches Feature, das es Ihnen ermöglicht, weniger und gleichzeitig effizienteren Code zu schreiben. Dieser Aspekt von Generics wird in Rezept 4.1 ausführlicher behandelt. Generics bieten große Programmiermöglichkeiten, aber diese Möglichkeiten bringen auch mehr Verantwortung mit sich, sie richtig zu nutzen. Wenn Sie überlegen, Ihre ArrayList-, Queue-, Stack- und Hashtable- Objekte in ihre generischen Gegenstücke umzuwandeln, sollten Sie die Rezepte 4.3, 4.4 und 4.9 lesen. Wie Sie dort erfahren werden, ist diese Umwandlung nicht immer einfach und leicht, und es gibt außerdem Gründe, diese Umwandlung überhaupt nicht auszuführen. Andere Rezepte in diesem Kapitel (wie Rezept 4.5) befassen sich mit anderen generischen Klassen aus Version 2.0 des.net Frameworks. Weitere befassen sich mit der Arbeitsweise beliebiger generischer Typen (wie die Rezepte 4.2, 4.7 und 4.12). 4.1 Entscheiden, wann und wo Generics verwendet werden sollten Problem Sie möchten in einem neuen Projekt generische Typen verwenden oder die Typen in einem vorhandenen Objekt in ihre generische Entsprechung umwandeln. Sie wissen allerdings eigentlich nicht so genau, warum Sie das tun sollten, und Sie wissen nicht, welche nicht-generischen Typen in generische Typen umgewandelt werden sollten. 140 Kapitel 4: Generics

2 Rechts Lösung Wenn Sie überlegen, wann und wo Sie generische Typen verwenden sollten, müssen Sie verschiedene Dinge in Erwägung ziehen: Enthält Ihr Typ verschiedene nicht festgelegte Datentypen oder operiert er auf solchen (z.b. einem Collection-Typ)? Wenn das der Fall ist, hat es eine Reihe von Vorteilen, wenn Sie statt eines nicht-generischen Typs einen generischen Typ verwenden. Wenn Ihr Typ nur auf einem einzigen festgelegten Datentyp operiert, dann müssen Sie vielleicht keinen generischen Typ verwenden. Wenn Ihr Typ auf Werttypen operiert, die Boxing- und Unboxing-Operationen erforderlich machen, sollten Sie überlegen, ob Sie generische Typen verwenden wollen, um das Boxing und Unboxing zu verhindern. Die strengere Typprüfung, die mit Generics verbunden ist, hilft Ihnen, Fehler schneller aufzufinden (d.h. schon zur Kompilierzeit und nicht erst zur Laufzeit), und verkürzt damit Ihren Fehlerprüfungszyklus. Leidet Ihr Code unter»code-schwemme«, d.h., müssen Sie mehrere Klassen schreiben, um die verschiedenen Datentypen zu handhaben, auf denen er operiert (z.b. eine spezialisierte ArrayList, die nur StreamReader speichert, und eine andere, die nur StreamWriter speichert)? Dann ist es einfacher, den Code nur einmal für jeden der Datentypen zu schreiben, mit denen er arbeitet. Generics sorgen dafür, dass der Code klarer ist. Indem sie eine Code-Schwemme verhindern und stärkere Typprüfungen für Ihre Typen erzwingen, bewirken sie, dass Ihr Code einfacher zu lesen und zu verstehen ist. Diskussion In den meisten Fällen profitiert Ihr Code, wenn Sie Generics verwenden. Generics bieten eine effizientere Code-Wiederverwendung, bessere Performance, strengere Typprüfungen und leichter zu lesenden Code. Siehe auch Die Themen»Generika«und»Vorteile von Generika«in der MSDN-Dokumentation. 4.2 Generische Typen verstehen Problem Sie müssen verstehen, wie die.net-typen für Generics funktionieren und was sie von gewöhnlichen.net-typen unterscheidet. 4.2 Generische Typen verstehen 141

3 Lösung Ein paar kleine Experimente können Ihnen den Unterschied zwischen gewöhnlichen.net-typen und generischen.net-typen klar machen. Wenn ein gewöhnlicher.net- Typ definiert ist, sieht er wie der Typ StandardClass aus, der in Beispiel 4-1 definiert wird. Links Beispiel 4-1: StandardClass: Ein gewöhnlicher.net-typ public class StandardClass // Der statische Zähler hält fest, wie viele Instanzen des Typs // StandardClass erzeugt wurden. static int _count = 0; // Ein Array für typisierte Elemente erzeugen. int _maxitemcount; object[] _items; int _currentitem = 0; // Ein Konstruktor, der den statischen Zähler inkrementiert. public StandardClass(int items) _count++; _maxitemcount = items; _items = new object[_maxitemcount]; /// <summary> /// Der Klasse ein Element hinzufügen, dessen Typ unbekannt ist, /// da nur object jeden beliebigen Typ festhalten kann. /// </summary> /// <param name="item">das hinzuzufügende Element</param> /// <returns>der Index des hinzugefügten Elements</returns> public int AddItem(object item) if (_currentitem < _maxitemcount) _items[_currentitem] = item; return _currentitem++; else throw new Exception("Element-Queue ist voll"); /// <summary> /// Ein Element aus der Klasse abrufen. /// </summary> /// <param name="index">der Index des abzurufenden Elements</param> /// <returns>ein Element des Typs object</returns> public object GetItem(int index) Debug.Assert(index < _maxitemcount); if (index >= _maxitemcount) throw new ArgumentOutOfRangeException("index"); 142 Kapitel 4: Generics

4 Rechts Beispiel 4-1: StandardClass: Ein gewöhnlicher.net-typ (Fortsetzung) return _items[index]; /// <summary> /// Die Anzahl der Elemente, die die Klasse enthält. /// </summary> public int ItemCount return _currentitem; /// <summary> /// ToString-Überschreibung, die Klasseninformationen liefert. /// </summary> /// <returns>formatierter String mit Klasseninformationen</returns> public override string ToString( ) return "Es gibt " + _count.tostring( ) + " Instanzen von " + this.gettype( ).ToString( ) + " die " + _currentitem + " Elemente des Typs " + _items.gettype( ).ToString( ) + " enthalten"; StandardClass hat eine statische Integer-Member-Variable, _count, die im Instanzkonstruktor inkrementiert wird, und eine ToString( )-Überschreibung, die ausgibt, wie viele Instanzen von StandardClass in dieser AppDomain existieren. StandardClass enthält außerdem ein Array mit object-elementen (_items), dessen Größe durch die Elementanzahl bestimmt wird, die an den Konstruktor übergeben wird. Sie implementiert Methoden zum Hinzufügen und Abrufen von Elementen (AddItem, GetItem) und ein schreibgeschütztes Property (ItemCount) für die Anzahl der Elemente im Array. Der Typ GenericClass<T> ist ein generischer.net-typ mit dem gleichen statischen Integer-Feld, _count, dem Konstruktor, der die Anzahl von erzeugten Instanzen zählt, und der überschriebenen ToString( )-Methode, die Ihnen sagt, wie viele Instanzen von diesem Typ es gibt. GenericClass<T> hat ebenfalls ein _items-array und Methoden, die den Methoden in StandardClass entsprechen, wie Sie in Beispiel 4-2 sehen können. Beispiel 4-2: GenericClass<T>: Ein generischer.net-typ public class GenericClass<T> // Der statische Zähler hält fest, wie viele Instanzen von // GenericClass erzeugt wurden. static int _count = 0; // Ein Array typisierter Typen erzeugen. int _maxitemcount; T[] _items; int _currentitem = 0; 4.2 Generische Typen verstehen 143

5 Beispiel 4-2: GenericClass<T>: Ein generischer.net-typ (Fortsetzung) // Konstruktor, der den statischen Zähler inkrementiert. public GenericClass(int items) _count++; _maxitemcount = items; _items = new T[_maxItemCount]; Links /// <summary> /// Der Klasse ein Element hinzufügen, dessen Typ durch den /// instanziierenden Typ festgelegt wird. /// </summary> /// <param name="item">das hinzuzufügende Element</param> /// <returns>der null-basierte Index des hinzugefügten Elements</returns> public int AddItem(T item) if (_currentitem < _maxitemcount) _items[_currentitem] = item; return _currentitem++; else throw new Exception("Element-Queue ist voll"); /// <summary> /// Ein Element aus der Klasse abrufen. /// </summary> /// <param name="index">der null-basierte Index des abzurufenden Elements</param> /// <returns>ein Element des instanziierenden Typs</returns> public T GetItem(int index) Debug.Assert(index < _maxitemcount); if (index >= _maxitemcount) throw new ArgumentOutOfRangeException("index"); return _items[index]; /// <summary> /// Die Anzahl der Elemente, die die Klasse enthält. /// </summary> public int ItemCount return _currentitem; /// <summary> /// ToString-Überschreibung, die Klasseninformationen liefert. /// </summary> /// <returns>formatierter String mit Klasseninformationen</returns> public override string ToString( ) 144 Kapitel 4: Generics

6 Rechts Beispiel 4-2: GenericClass<T>: Ein generischer.net-typ (Fortsetzung) return "Es gibt " + _count.tostring( ) + " Instanzen des Typs " + this.gettype( ).ToString( ) + " die " + _currentitem + " Elemente des Typs " + _items.gettype( ).ToString( ) + " enthalten"; Wenn Sie sich die Implementierung des Arrays _items in GenericClass<T> ansehen, werden Sie feststellen, dass die Dinge hier beginnen, anders auszusehen. Das Array _items ist folgendermaßen deklariert: T [] _items; Und nicht mehr so: object [] _items; Das Array _items nutzt den Typparameter der generischen Klasse (<T>), um zu bestimmen, welche Elemente mit welchen Typen im Array _items erlaubt sein sollen. StandardClass nutzt object für den Typ des Arrays _items und erlaubt damit, dass Elemente beliebigen Typs im Array gespeichert werden können (da alle Typen von object abgeleitet sind), während GenericClass<T> Typsicherheit bietet, indem sie dem Typparameter ermöglicht festzulegen, was für Objekte welches Typs erlaubt sind. Der nächste Unterschied wird in den Methodendeklarationen von AddItem und GetItem sichtbar. AddItem akzeptiert jetzt einen Parameter des Typs T, StandardClass nahm hingegen einen Parameter des Typs object entgegen. GetItem liefert jetzt einen Wert des Typs T zurück, StandardClass hingegen lieferte einen Wert des Typs object zurück. Diese Änderungen erlauben den Methoden in GenericClass<T>, den instanziierten Typ zu verwenden, um die Elemente im Array zu speichern und aus ihm abzurufen, anstatt zu erlauben, dass jedes object in StandardClass gespeichert wird. /// <summary> /// Der Klasse ein Element hinzufügen, dessen Typ durch den /// instanziierenden Typ festgelegt wird. /// </summary> /// <param name="item">hinzuzufügendes Element</param> /// <returns>der null-basierte Index des hinzugefügten Elements</returns> public int AddItem(T item) if (_currentitem < _maxitemcount) _items[_currentitem] = item; return _currentitem++; else throw new Exception("Element-Queue ist voll"); /// <summary> /// Ein Element aus der Klasse abrufen. 4.2 Generische Typen verstehen 145

7 /// </summary> /// <param name="index">der null-basierte Index des abzurufenden Elements</param> /// <returns>ein Element des instanziierenden Typs</returns> public T GetItem(int index) Debug.Assert(index < _maxitemcount); if (index >= _maxitemcount) throw new ArgumentOutOfRangeException("index"); Links return _items[index]; Das bietet ein paar Vorteile. Der erste und wichtigste ist, dass GenericClass<T> Typsicherheit für die Elemente im Array bietet. Bei StandardClass hätte man Code wie den folgenden schreiben können: // Gewöhnliche Klasse StandardClass C = new StandardClass(5); Console.WriteLine(C); string s1 = "s1"; string s2 = "s2"; string s3 = "s3"; int i1 = 1; // StandardClass etwas (als object) hinzufügen. C.AddItem(s1); C.AddItem(s2); C.AddItem(s3); // Dem String-Array einen int hinzufügen, vollkommen OK. C.AddItem(i1); Aber bei GenericClass<T> erhalten Sie einen Compiler-Fehler, wenn Sie das Gleiche versuchen: // Generische Klasse GenericClass<string> gc = new GenericClass<string>(5); Console.WriteLine(gC); string s1 = "s1"; string s2 = "s2"; string s3 = "s3"; int i1 = 1; // GenericClass etwas (als string) hinzufügen. gc.additem(s1); gc.additem(s2); gc.additem(s3); // Der Versuch, der string-instanz einen int hinzuzufügen, wird // vom Compiler unterbunden: error CS1503: Das Argument // 1 kann nicht von int in string konvertiert werden. // gc.additem(s3); Dass der Compiler das verhindert, bevor es zur Ursache von Laufzeitfehlern wird, ist eine gute Sache. 146 Kapitel 4: Generics

8 Rechts Vielleicht fällt es nicht sofort ins Auge, aber der Integer wird eigentlich geboxt, wenn er dem object-array in StandardClass hinzugefügt wird, wie Sie am IL-Code für den GetItem- Aufruf auf StandardClass sehen: IL_0170: ldloc.2 IL_0171: ldloc.s IL_0173: box IL_0178: callvirt i1 [mscorlib]system.int32 instance int32 CSharpRecipes.Generics/StandardClass::AddItem(object) Dieses Boxing wandelt den int, einen Werttyp, in einen Referenztyp (object) um, um ihn im Array speichern zu können. Das ist dafür verantwortlich, dass zusätzliche Arbeit ausgeführt werden muss, um Werttypen im object-array zu speichern. Außerdem gibt es ein Problem, wenn Sie ein Element aus der Klasse in der StandardClass- Implementierung zurückerhalten. Sehen Sie sich an, wie StandardClass.GetItem ein Element abruft: // Den abgerufenen String festhalten. string sholder; // Cast erforderlich, um folgenden Fehler zu vermeiden: error CS0266: // Der Typ object kann nicht implizit in string konvertiert werden... sholder = (string)c.getitem(1); Da das von StandardClass.GetItem zurückgelieferte Element den Typ object hat, muss es auf einen string gecastet werden, um das Element für den Index 1 zurückzuerhalten, von dem Sie hoffen, dass es ein string ist. Aber vielleicht ist es gar kein string sicher können Sie nur wissen, dass es ein object ist, aber wenn es herauskommt, müssen Sie es auf einen spezifischeren Typ casten, damit Sie es ordentlich zuweisen können. strings sind ein besonderer Fall, da alle objects eine Stringdarstellung ihrer selbst liefern können. Aber Sie können sehen, wie das zu einem Problem werden könnte, wenn das Array einen double enthielte und der zurückgelieferte Wert einer bool-variable zugewiesen werden sollte. Beide Probleme werden durch die GenericClass<T>-Implementierung behoben. Das Unboxing-Problem wird gelöst. Es ist kein Unboxing erforderlich, da der Rückgabetyp von GetItem dem instanziierten Typ entspricht und der Compiler das erzwingt, indem er den Rückgabetyp betrachtet: // Den abgerufenen String festhalten. string sholder; int iholder; // Kein Cast erforderlich sholder = gc.getitem(1); // Versuchen, einen String in einen int abzurufen. // CS0029: Der Typ string kann nicht implizit in int konvertiert werden. // iholder = gc.getitem(1); Instanziieren Sie ein paar Instanzen beider Typen, um die anderen Unterschiede zwischen ihnen zu erkennen: 4.2 Generische Typen verstehen 147

9 // Gewöhnliche Klasse StandardClass A = new StandardClass( ); Console.WriteLine(A); StandardClass B = new StandardClass( ); Console.WriteLine(B); StandardClass C = new StandardClass( ); Console.WriteLine(C); Links // Generische Klasse GenericClass<bool> ga = new GenericClass<bool>( ); Console.WriteLine(gA); GenericClass<int> gb = new GenericClass<int>( ); Console.WriteLine(gB); GenericClass<string> gc = new GenericClass<string>( ); Console.WriteLine(gC); GenericClass<string> gd = new GenericClass<string>( ); Console.WriteLine(gD); Die Ausgabe dieses Codes sieht folgendermaßen aus: Es gibt 1 Instanzen von CSharpRecipes.Generics+StandardClass die 0 Elemente des Typs System.Object[] enthalten Es gibt 2 Instanzen von CSharpRecipes.Generics+StandardClass die 0 Elemente des Typs System.Object[] enthalten Es gibt 3 Instanzen von CSharpRecipes.Generics+StandardClass die 0 Elemente des Typs System.Object[] enthalten Es gibt 1 Instanzen von CSharpRecipes.Generics+GenericClass`1[System.Boolean] die 0 Elemente des Typs System.Boolean[] enhalten Es gibt 1 Instanzen von CSharpRecipes.Generics+GenericClass`1[System.Int32] die 0 Elemente des Typs System.Int32[] enthalten Es gibt 1 Instanzen von CSharpRecipes.Generics+GenericClass`1[System.String] die 0 Elemente des Typs System.String[] enthalten Es gibt 2 Instanzen von CSharpRecipes.Generics+GenericClass`1[System.String] die 0 Elemente des Typs System.String[] enthalten Diskussion Die Typparameter von Generics ermöglichen es Ihnen, typsicheren Code zu erstellen, ohne dass Sie dazu wissen müssen, mit welchem Typ Sie tatsächlich arbeiten müssen. Bei vielen Instanzen wollen Sie, dass die Typen bestimmte Charakteristika haben. In diesem Fall können Sie den Typ (Rezept 4.11) einschränken. Methoden können auch dann generische Typparameter haben, wenn die Klasse selbst sie nicht hat. Rezept 4.8 zeigt ein Beispiel dafür. Beachten Sie, dass StandardClass drei Instanzen hat. GenericClass hingegen hat eine Instanz, bei der der Typ als <bool> deklariert wurde, und zwei Instanzen, bei denen der Typ als <string> deklariert wurde. Das bedeutet, dass nur ein.net-type-objekt für jede nicht-generische Klasse erzeugt wird, aber jeweils ein.net-type-objekt für jede spezifische Instanziierung einer generischen Klasse. Im Beispielcode gibt es drei Instanzen für StandardClass, weil es für StandardClass nur einen Typ gibt, der von der CLR verwaltet wird. Bei Generics wird ein Typ für jede Kom- 148 Kapitel 4: Generics

10 Rechts bination von Klassenschablone und Typargument erzeugt, das übergeben wird, wenn eine Typinstanz konstruiert wird. Um das noch klarer zu machen: Sie erhalten einen.net-typ für GenericClass<bool>, ein zweiten.net-typ für GenericClass<int> und einen dritten.net-typ für GenericClass<string>. Das interne statische Member _count hilft, diesen Punkt zu illustrieren, weil statische Member einer Klasse mit dem Typ verbunden sind, den die CLR ihnen zuweist. Die CLR erzeugt jeden Typ nur einmal und pflegt ihn dann, bis die AppDomain entladen wird. Das ist der Grund dafür, dass die Aufrufe von ToString( ) auf diesen Objekten anzeigen, dass die aktuelle Anzahl für StandardClass drei ist (da es diesen Typ tatsächlich nur einmal gibt), und zweimal eins und einmal zwei für die Anzahl von GenericClass<T>-Typen melden. Siehe auch Die Themen»Generische Typparameter«und»Generische Klassen«in der MSDN-Dokumentation. 4.3 ArrayList durch das generische Gegenstück ersetzen Problem Sie möchten die Performance Ihrer Anwendung verbessern und die Arbeit mit Ihrem Code erleichtern, indem Sie alle ArrayList-Objekte durch die generischen Versionen ersetzen. Das ist notwendig, wenn Sie feststellen, dass Strukturen oder andere Werttypen in diesen Datenstrukturen gespeichert werden und dadurch Boxing/Unboxing-Operationen veranlasst werden. Lösung Ersetzen Sie alle Vorkommen der Klasse System.Collection.ArrayList durch die effizientere generische Klasse System.Collections.Generic.List. Hier ist ein einfaches Beispiel, das ein System.Collections.ArrayList-Objekt verwendet: public static void UseNonGenericArrayList( ) // Eine ArrayList erzeugen und füllen. ArrayList numbers = new ArrayList( ); numbers.add(1); // Bewirkt eine Boxing-Operation numbers.add(2); // Bewirkt eine Boxing-Operation // Alle Integer in der ArrayList anzeigen. // Bewirkt, dass bei jeder Iteration eine Unboxing-Operation // stattfindet foreach (int i in numbers) 4.3 ArrayList durch das generische Gegenstück ersetzen 149

11 Console.WriteLine(i); Links numbers.clear( ); Hier ist der gleiche Code, wenn stattdessen ein System.Collections.Generic.List-Objekt verwendet wird: public static void UseGenericList( ) // Eine Liste erzeugen und füllen. List<int> numbers = new List<int>( ); numbers.add(1); numbers.add(2); // Alle Integer in der ArrayList anzeigen. foreach (int i in numbers) Console.WriteLine(i); numbers.clear( ); Diskussion Da ArrayLists in fast allen Anwendungen verwendet werden, ist das ein guter Ansatzpunkt, um die Leistung Ihrer Anwendung zu verbessern. Bei den einfachen Implementierungen von ArrayList in Ihrer Anwendung sollte diese Ersetzung recht problemlos verlaufen. Sie müssen allerdings auf ein paar Dinge achten. Beispielsweise implementiert die generische Klasse List das Interface ICloneable nicht, während die Klasse ArrayList das macht. Tabelle 4-1 zeigt die äquivalenten Member, die beide Klassen implementieren. Tabelle 4-1: Äquivalente Member in ArrayList und den generischen List-Klassen Member in der Klasse ArrayList Capacity-Property Count-Property IsFixedSize-Property IsReadOnly-Property IsSynchronized-Property Item-Property SyncRoot-Property Adapter-Methode (statisch) Add-Methode Äquivalente Member in der generischen List-Klasse Capacity-Property Count-Property ((IList)myList).IsFixedSize ((IList)myList).IsReadOnly ((IList)myList).IsSynchronized Item-Property ((IList)myList).SyncRoot N/A Add-Methode 150 Kapitel 4: Generics

12 Rechts Tabelle 4-1: Äquivalente Member in ArrayList und den generischen List-Klassen (Fortsetzung) Member in der Klasse ArrayList AddRange-Methode N/A BinarySearch-Methode Clear-Methode Clone-Methode Contains-Methode N/A CopyTo-Methode N/A N/A N/A N/A N/A N/A N/A FixedSize-Methode (statisch) GetRange-Methode IndexOf-Methode Insert-Methode InsertRange-Methode LastIndexOf-Methode ReadOnly static-methode Remove-Methode N/A RemoveAt-Methode RemoveRange-Methode Repeat-Methode (statisch) Reverse-Methode SetRange-Methode Sort-Methode Synchronized-Methode (statisch) ToArray-Methode N/A TrimToSize-Methode N/A Äquivalente Member in der generischen List-Klasse AddRange-Methode AsReadOnly-Methode BinarySearch-Methode Clear-Methode GetRange(0, numbers.count) Contains-Methode ConvertAll-Methode CopyTo-Methode Exists-Methode Find-Methode FindAll-Methode FindIndex-Methode FindLast-Methode FindLastIndex-Methode ForEach-Methode N/A GetRange-Methode IndexOf-Methode Insert-Methode InsertRange-Methode LastIndexOf-Methode AsReadOnly-Methode Remove-Methode RemoveAll-Methode RemoveAt-Methode RemoveRange-Methode Verwenden Sie eine for-schleife und die Methode Add Reverse-Methode InsertRange-Methode Sort-Methode lock(mylist.syncroot) ToArray-Methode TrimExcess-Methode TrimToSize-Methode TrueForAll-Methode 4.3 ArrayList durch das generische Gegenstück ersetzen 151

13 In vielen Fällen gibt es in Tabelle 4-1 eine Eins-zu-eins-Entsprechung zwischen den Membern von ArrayList und den Membern der generischen Klasse List. Beginnen wir mit den Properties: Beachten Sie, dass nur die Properties Capacity, Count und Item in beiden Klassen vorhanden sind. Um die fehlenden Properties in der Klasse List zu kompensieren, können Sie einen Cast auf die Klasse IList durchführen. Der folgende Code zeigt, wie Sie diesen Cast ausführen, um an die fehlenden Properties zu kommen: List<int> numbers = new List<int>( ); Links Console.WriteLine(((IList)numbers).IsReadOnly); Console.WriteLine(((IList)numbers).IsFixedSize); Console.WriteLine(((IList)numbers).IsSynchronized); Console.WriteLine(((IList)numbers).SyncRoot); Beachten Sie, dass die Properties IsFixedSize und IsSynchronized immer false zurückliefern, da es bei einer generischen List keinen Code gibt, der eine synchronisierte Version von List zurückliefert, und da es ebenfalls keinen Code gibt, der eine List fester Größe zurückliefert. Das Property SyncRoot liefert immer das Objekt zurück, auf dem es aufgerufen wurde. Dieses Property liefert immer den this-zeiger zurück. Microsoft hat sich entschieden, die Fähigkeit, einen synchronen Wrapper für eine der generischen Collection- Klassen zurückzuliefern, zu entfernen. Stattdessen empfiehlt Microsoft, das Schlüsselwort lock zu verwenden, um die vollständige Collection zu sperren, oder einen anderen Typ von Synchronisationsobjekt zu verwenden, das Ihren Bedürfnissen entspricht. ArrayList hat eine Reihe von statischen Methoden, für die es kein Äquivalent in der generischen List-Klasse gibt. Um das zu beheben, müssen Sie etwas Arbeit investieren. Der statischen Methode ArrayList.ReadOnly kommt die AsReadOnly-Instanzmethode der generischen List-Klasse am nächsten. Das ermöglicht eine recht einfache Ersetzung. Für die statische Methode ArrayList.Repeat gibt es in der generischen List-Klasse kein Äquivalent. Stattdessen können Sie die folgende generische Methode verwenden: public static void Repeat<T>(List<T> list, T obj, int count) if (count < 0) throw (new ArgumentException( "Der Parameter count muss größer, gleich 0 sein.")); for (int index = 0; index < count; index++) list.add(obj); Diese generische Methode akzeptiert drei Parameter: list Das generische List-Objekt. 152 Kapitel 4: Generics

14 Rechts obj Das Objekt, das dem generischen List-Objekt eine bestimmte Anzahl von Malen hinzugefügt werden soll. count Eine Zahl, die angibt, wie oft das in obj enthaltene Objekt dem generischen List- Objekt hinzugefügt werden soll. Da der generischen Klasse List die Methode Clone fehlt (weil diese Klasse das Interface ICloneable nicht implementiert), können Sie stattdessen die GetRange-Methode der generischen List-Klasse verwenden. List<int> oldlist = new List<int>( ); // oldlist füllen... List<int> newlist = oldlist.getrange(0, oldlist.count); Die Methode GetRange führt (wie die Clone-Methode von ArrayList) eine flache Kopie eines Bereichs der Elemente im List-Objekt durch. In diesem Fall schließt der Bereich alle Elemente ein. Siehe auch Eine ArrayList hat zu Anfang per Default eine Kapazität von 16 Elementen, während die Default-Anfangskapazität einer List<T> nur 4 Elemente beträgt. Das bedeutet, dass die List<T> dreimal vergrößert (und neu alloziert) werden muss, bis das 17. Element hinzugefügt wurde, während die ArrayList nur ein einziges Mal vergrößert werden müsste. Das sollten Sie nicht vergessen, wenn Sie die Performance Ihrer Anwendung auswerten. Die Themen»System.Collections.ArrayList-Klasse«und»System.Collections.Generic.List- Klasse«in der MSDN-Dokumentation. 4.4 Stack und Queue durch ihre generischen Gegenstücke ersetzen Problem Sie möchten die Leistung Ihrer Anwendung verbessern und die Arbeit mit Ihrem Code vereinfachen, indem Sie alle Stack- und Queue-Objekte durch die generischen Versionen ersetzen. Das ist auf alle Fälle erforderlich, wenn Sie feststellen, dass in diesen Datenstrukturen Strukturen oder andere Werttypen gespeichert werden, die bewirken, dass Boxing/Unboxing-Operationen durchgeführt werden müssen. 4.4 Stack und Queue durch ihre generischen Gegenstücke ersetzen 153

15 Lösung Ersetzen Sie alle Vorkommen von System.Collections.Stack- und System.Collection. Queue-Objekten durch System.Collections.Generic.Stack- und System.Collection.Generic.Queue-Objekte. Hier ist ein Beispiel, in dem ein System.Collections.Queue-Objekt verwendet wird: public static void UseNonGenericQueue( ) // Ein nicht-generisches Queue-Objekt erzeugen. Queue numericqueue = new Queue( ); Links // Queue füllen (bewirkt jeweils eine Boxing-Operation). numericqueue.enqueue(1); numericqueue.enqueue(2); numericqueue.enqueue(3); // Queue leeren und Elemente anzeigen (bewirkt jeweils eine Unboxing-Operation) Console.WriteLine(numericQueue.Dequeue( )); Console.WriteLine(numericQueue.Dequeue( )); Console.WriteLine(numericQueue.Dequeue( ).ToString( )); Hier ist der gleichwertige Code, der ein System.Collections.Generic.Queue-Objekt verwendet: public static void UseGenericQueue( ) // Ein generisches Queue-Objekt erzeugen. Queue<int> numericqueue = new Queue<int>( ); // Queue füllen. numericqueue.enqueue(1); numericqueue.enqueue(2); numericqueue.enqueue(3); // Queue leeren und Elemente anzeigen. Console.WriteLine(numericQueue.Dequeue( )); Console.WriteLine(numericQueue.Dequeue( )); Console.WriteLine(numericQueue.Dequeue( )); Hier ist ein einfaches Beispiel für die Verwendung eines System.Collections.Stack-Objekts: public static void UseNonGenericStack( ) // Ein nicht-generisches Stack-Objekt erzeugen. Stack numericstack = new Stack( ); // Stack füllen (bewirkt jeweils eine Boxing-Operation). numericstack.push(1); numericstack.push(2); numericstack.push(3); 154 Kapitel 4: Generics

16 Rechts // Stack leeren und Elemente anzeigen (bewirkt jeweils eine Unboxing-Operation). Console.WriteLine(numericStack.Pop( ).ToString( )); Console.WriteLine(numericStack.Pop( ).ToString( )); Console.WriteLine(numericStack.Pop( ).ToString( )); Hier ist gleichwertiger Code, der ein System.Collections.Generic.Stack-Objekt verwendet: public static void UseGenericStack( ) // Ein generisches Stack-Objekt erzeugen. Stack<int> numericstack = new Stack<int>( ); // Stack füllen. numericstack.push(1); numericstack.push(2); numericstack.push(3); // Stack leeren und Elemente anzeigen. Console.WriteLine(numericStack.Pop( ).ToString( )); Console.WriteLine(numericStack.Pop( ).ToString( )); Console.WriteLine(numericStack.Pop( ).ToString( )); Diskussion Oberflächlich betrachtet, sehen sich die generischen und die nicht-generischen Versionen von Queue und Stack ziemlich ähnlich. Unter der Oberfläche sieht die Sache aber ganz anders aus. Die grundlegende Verwendung der generischen Queue- und Stack-Objekte gleicht der Verwendung ihrer nicht-generischen Gegenstücke. Nur die Syntax zur Instanziierung der Objekte ist eine andere. Die generische Form erfordert ein Typargument, damit der Typ erstellt werden kann. In diesem Beispiel ist das Typargument int. Dieses Typargument gibt an, dass diese Queue bzw. dieser Stack nur Integer-Typen oder Typen enthält, die sich implizit in einen Integer umwandeln lassen wie short: short s = 300; numericqueue.enqueue(s); // OK, wegen impliziter Typumwandlung Ein Typ, der nicht implizit in einen Integer umgewandelt werden kann (wie ein double) verursacht hingegen einen Compiler-Fehler: double d = 300; numericqueue.enqueue(d); numericqueue.enqueue((int)d); // Fehler, kein impliziter Cast verfügbar // OK, expliziter Cast Bei der nicht-generischen Form ist dieses Typargument nicht erforderlich, weil nichtgenerische Queue- und Stack-Objekte nur Elemente vom Typ Object enthalten können. Wenn Sie die Wahl zwischen einer/einem generischen oder einer/einem nicht-generischen Queue bzw. Stack treffen, müssen Sie entscheiden, ob Sie ein streng typisiertes Queue- oder Stack-Objekt (d.h. die generische Queue- oder Stack-Klasse) oder ein schwach typisiertes 4.4 Stack und Queue durch ihre generischen Gegenstücke ersetzen 155

17 Queue- oder Stack Objekt (d.h. die nicht-generische Queue- oder Stack-Klasse) wollen. Es bietet Ihnen einige Vorteile, wenn Sie statt der nicht-generischen Formen eine generische Queue- oder Stack-Klasse wählen: Typsicherheit Alle Elemente, die in der Datenstruktur enthalten sind, müssen einen vorgegebenen Typ haben. Das bedeutet, dass keine Objekte mehr gecastet werden müssen, wenn sie der Datenstruktur hinzugefügt oder aus der Datenstruktur herausgenommen werden. Sie können in einer Datenstruktur nicht mehrere verschiedene Typen speichern. Sie wissen immer, welcher Typ in der Datenstruktur gespeichert ist. Die Typprüfung erfolgt zur Kompilierzeit, nicht zur Laufzeit. Das führt dazu, dass Sie weniger Code schreiben müssen, bessere Ergebnisse erhalten und weniger Fehler machen. Kürzere Entwicklungszeit Wenn Sie eine typsichere Datenstruktur ohne Generics erstellen wollen, müssen Sie eine Unterklasse der Klassen System.Collections.Queue oder System.Collections. Stack bilden, um eine eigene Datenstruktur zu erzeugen. Das ist zeitaufwändig und fehleranfällig. Generics ermöglichen es Ihnen, dem Queue- oder Stack-Objekt zur Kompilierzeit zu sagen, welchen Typ es enthalten darf. Performance Bei den generischen Queue- oder Stack-Klassen muss kein wahrscheinlich zeitaufwändiger Cast erfolgen, wenn Elemente hinzugefügt oder herausgenommen werden. Außerdem ist keine Boxing-Operation erforderlich, wenn einer Queue oder einem Stack ein Werttyp hinzugefügt wird. Und es ist ebenfalls keine Unboxing-Operation erforderlich, wenn ein Werttyp aus einer Queue oder einem Stack herausgeholt wird. Besser lesbarer Code Ihre Codebasis wird erheblich schlanker sein, weil Sie keine Unterklassen für die nicht-generischen Klassen Queue oder Stack bilden müssen, um Ihre eigenen streng typisierten Klassen zu erzeugen. Außerdem sorgen die Typsicherheits-Features von generischem Code dafür, dass man besser versteht, welchem Zweck eine Queue oder ein Stack in Ihrem Code dient. Ein Unterschied zwischen den generischen und nicht-generischen Queue- und Stack-Klassen ist, welche Member in den einzelnen Klassen implementiert sind. Die Member, die in den nicht-generischen Queue- und Stack-Klassen implementiert sind, aber nicht in den generischen Queue- und Stack-Klassen, werden hier aufgeführt: Clone-Methode IsSynchronized-Property SyncRoot-Property Synchronized-Methode Dass die nicht-generischen Queue- und Stack-Klassen die zusätzliche Clone-Methode haben, liegt daran, dass das Interface ICloneable nur von den nicht-generischen Queueund Stack-Klassen implementiert wird. Ansonsten implementieren die generischen und nicht-generischen Queue- und Stack-Klassen die gleichen Interfaces. Links 156 Kapitel 4: Generics

18 Rechts Eine Möglichkeit, das Fehlen der Clone-Methode in den generischen Queue- und Stack- Klassen zu umgehen, bietet der Konstruktor, der einen IEnumerable<T>-Typ akzeptiert. Da das eines der Interfaces ist, das die Klassen Queue und Stack implementieren, ist der entsprechende Code leicht zu schreiben. Für ein Queue-Objekt sähe dieser Code so aus: public static void CloneQueue( ) // Ein generisches Queue-Objekt erzeugen. Queue<int> numericqueue = new Queue<int>( ); // Queue füllen. numericqueue.enqueue(1); numericqueue.enqueue(2); numericqueue.enqueue(3); // Einen Klon von numericqueue erstellen. Queue<int> clonednumericqueue = new Queue<int>(numericQueue); // Hiermit werfen wir einfach einen Blick auf die Werte, ohne // sie aus der Queue herauszunehmen. foreach (int i in clonednumericqueue) Console.WriteLine("foreach: " + i.tostring( )); // Queue leeren und Elemente anzeigen. Console.WriteLine(clonedNumericQueue.Dequeue( ).ToString( )); Console.WriteLine(clonedNumericQueue.Dequeue( ).ToString( )); Console.WriteLine(clonedNumericQueue.Dequeue( ).ToString( )); Die Ausgabe dieser Methode sehen Sie hier: foreach: 1 foreach: 2 foreach: Der Code für das Stack-Objekt sieht so aus: public static void CloneStack( ) // Ein generisches Stack-Objekt erzeugen. Stack<int> numericstack = new Stack<int>( ); // Stack füllen. numericstack.push(1); numericstack.push(2); numericstack.push(3); // Das Objekt numericstack klonen. Stack<int> clonednumericstack = new Stack<int>(numericStack); 4.4 Stack und Queue durch ihre generischen Gegenstücke ersetzen 157

19 // Hiermit werfen wir einfach einen Blick auf die Werte, ohne // sie aus dem Stack herauszunehmen. foreach (int i in clonednumericstack) Console.WriteLine("foreach: " + i.tostring( )); Links // Stack leeren und Elemente anzeigen. Console.WriteLine(clonedNumericStack.Pop( ).ToString( )); Console.WriteLine(clonedNumericStack.Pop( ).ToString( )); Console.WriteLine(clonedNumericStack.Pop( ).ToString( )); Die Ausgabe für die Methode sehen Sie hier: foreach: 1 foreach: 2 foreach: Dieser Konstruktor erzeugt eine neue Instanz der Klassen Queue oder Stack, die die Elemente enthalten, die aus dem IEnumerable<T>-Typ kopiert werden. Siehe auch Die Themen»System.Collections.Stack-Klasse«,»System.Collections.Generic.Stack- Klasse«,»System.Collections.Queue-Klasse«und»System.Collections.Generic.Queue- Klasse«in der MSDN-Dokumentation. 4.5 Eine verkette Liste (LinkedList) implementieren Problem Sie benötigen eine verkettete Datenstruktur, die es Ihnen ermöglicht, einfach Elemente hinzuzufügen und zu entfernen. Lösung Verwenden Sie die generische Klasse LinkedList<T>. Die folgende Methode erzeugt ein Objekt der Klasse LinkedList<T>, fügt diesem Objekt Knoten hinzu und verwendet dann verschiedene Methoden, um Informationen über die Knoten in der verketteten Liste zu erhalten: public static void UseLinkedList( ) // Ein neues LinkedList-Objekt erzeugen. LinkedList<TodoItem> todolist = new LinkedList<TodoItem>( ); 158 Kapitel 4: Generics

20 Rechts // TodoItem-Objekte erstellen, die der verketteten Liste hinzugefügt werden. TodoItem i1 = new TodoItem("Tür streichen", "Sollte als Drittes gemacht werden"); TodoItem i2 = new TodoItem("Tür kaufen", "Sollte als Erstes gemacht werden"); TodoItem i3 = new TodoItem("Tür aufbauen", "Sollte als Zweites gemacht werden"); TodoItem i4 = new TodoItem("Tür einhängen", "Sollte als Letztes gemacht werden"); // Die Elemente hinzufügen. todolist.addfirst(i1); todolist.addfirst(i2); todolist.addbefore(todolist.find(i1), i3); todolist.addafter(todolist.find(i1), i4); // Alle Elemente anzeigen. foreach (TodoItem tdi in todolist) Console.WriteLine(tdi.Name + " : " + tdi.comment); // Informationen aus dem zweiten Knoten der Liste anzeigen. Console.WriteLine("todoList.First.Next.Value.Name == " + todolist.first.next.value.name); // Informationen aus dem vorletzten Knoten der Liste anzeigen. Console.WriteLine("todoList.Last.Previous.Value.Name == " + todolist.last.previous.value.name); Die Ausgabe für diese Methode sehen Sie hier: Tür kaufen : Sollte als Erstes gemacht werden Tür aufbauen : Sollte als Zweites gemacht werden Tür streichen : Sollte als Drittes gemacht werden Tür einhängen : Sollte als Letztes gemacht werden todolist.first.next.value.name == Tür aufbauen todolist.last.previous.value.name == Tür streichen Das ist die Klasse TodoItem, die ein einfacher Container für zwei Strings, _name und _comment, ist. public class TodoItem public TodoItem (string name, string comment) _name = name; _comment = comment; private string _name = ""; private string _comment = ""; public string Name return (_name); set _name = value; 4.5 Eine verkette Liste (LinkedList) implementieren 159

21 Links public string Comment return (_comment); set _comment = value; Diskussion Die Klasse LinkedList<T> des.net Frameworks wird als eine doppelt verkettete Liste betrachtet. Das liegt daran, dass jeder Knoten in der Liste einen Zeiger auf den in der Liste vorangehenden Knoten und einen Zeiger auf den in der Liste nachfolgenden Knoten enthält. Abbildung 4-1 zeigt, wie auf dem Papier ein Diagramm für eine doppelt-verkettete Liste aussehen würde. Jeder Knoten im Diagramm repräsentiert ein einzelnes LinkedListNode<T>-Objekt. Abbildung 4-1: Grafische Darstellung einer doppelt verketteten Liste mit drei Knoten Beachten Sie, dass jeder Knoten (d.h. jeder der rechteckigen Kästen) einen Zeiger auf den nächsten Knoten (der nach rechts zeigende Pfeil) und einen Zeiger auf den vorangehenden Knoten (der nach links zeigende Pfeil) in der verketteten Liste enthält. Im Unterschied dazu enthält eine einfach verkettete Liste nur Zeiger auf den in der Liste nachfolgenden Knoten. Es gibt keinen Zeiger auf den vorangehenden Knoten. In der Klasse LinkedList<T> greift man auf den vorangehenden Knoten immer über das Property Previous zu, und auf den nachfolgenden Knoten greift man immer über das Property Next zu. Das Previous-Property des ersten Knotens der verketteten Liste liefert immer null zurück. Gleichermaßen liefert das Next-Property der verketteten Liste immer null zurück. Jeder Knoten in der Liste (die in Abbildung 4-1 durch die Kästen repräsentiert werden) ist eigentlich ein generisches LinkedListNode<T>-Objekt. Ein LinkedList<T>-Objekt ist also eigentlich eine Collection von LinkedListNode<T>-Objekten. Jedes dieser Linked- ListNode<T>-Objekte enthält Properties für den Zugriff auf das vorangehende und das nachfolgende LinkedListNode<T>-Objekt und das Objekt, das in ihm enthalten ist. Auf das Objekt, das im LinkedListNode<T>-Objekt enthalten ist, wird über das Property Value zugegriffen. Außer diesen Properties enthält ein LinkedListNode<T>-Objekt außerdem noch ein Property namens List, das den Zugriff auf das enthaltende LinkedList<T>-Objekt ermöglicht. Was die Performance betrifft, bietet die Klasse List<T> Vorteile vor der Klasse Linked- List<T>. Das Hinzufügen und Entfernen von Knoten geht bei einer List<T> in der Regel 160 Kapitel 4: Generics

22 Rechts schneller als die gleiche Operation auf einer LinkedList<T>. Vergleicht man die Methode List<T>.Add mit den Add*-Methoden der Klasse LinkedList<T>, liegen die Performance- Vorteile weniger in der eigentlichen Hinzufügungsoperation als in dem Druck, den die LinkedList<T> auf den Garbage Collector ausübt. Eine List<T> speichert ihre Daten im Wesentlichen in einem großen Array, das auf dem Heap verwaltet wird, während die LinkedList<T> ihre Knoten auf dem gesamten Heap verstreut speichern kann. Das zwingt den Garbage Collector, viel mehr Arbeit zu leisten, um LinkedList<T>-Knotenobjekte auf dem verwalteten Heap zu verwalten. Beachten Sie, dass die List<T>.Insert*-Methoden langsamer sein können als die Hinzufügung eines Knotens an beliebiger Stelle einer LinkedList<T> über eine der Add*-Methoden. Das ist allerdings davon abhängig, wo das Objekt in die List<T> eingefügt werden muss. Eine Insert-Methode muss in der List<T> alle Elemente ab dem Punkt um eine Position verschieben, an dem das neue Objekt eingefügt wurde. Wenn das neue Element in der Nähe des Endes der List<T> eingefügt wird, ist der Aufwand für die Verschiebung der vorhandenen Elemente im Vergleich zum Garbage Collector-Aufwand für die Verwaltung der LinkedList<T>-Knotenobjekte eher gering. Eine List<T> kann auch leistungsfähiger als eine LinkedList<T> sein, wenn Sie indizierten Zugriff verwenden. Bei der List<T> kann man einen Indexer verwenden, um eine indizierte Suche nach dem Element an der angegebenen Position durchzuführen. Diesen Luxus gibt es bei einer LinkedList<T> nicht. Bei der Klasse LinkedList<T> müssen Sie über die Properties Previous und Next der LinkedListNode<T>-Objekte durch die LinkedListNode<T>- Objekte navigieren und die Liste durchlaufen, bis die angegebene Position erreicht wird. Eine List<T> ist auch leistungsfähiger als eine LinkedList<T>, wenn nach einem Element oder einem Knoten gesucht wird. Die Methode List<T>.BinarySearch findet Elemente in einem List<T>-Objekt schneller als die vergleichbaren Methoden der Klasse Linked- List<T>, die Methoden Contains, Find und FindLast. Das liegt daran, dass die Linked- List<T>-Methoden eine lineare Suche durchführen, die Methode List<T>.BinarySearch hingegen eine binäre Suche durchführt. Einfach gesagt, eine binäre Suche nutzt es aus, dass die Elemente in der List<T> sortiert sind. Das heißt aber auch, dass die Methode Sort aufgerufen werden muss, bevor die Methode BinarySearch verwendet wird. (Beachten Sie, dass die Methode Sort erneut ausgeführt werden muss, wenn ein Element hinzugefügt wurde, bevor die Methode BinarySearch aufgerufen wurde.) Auf Basis der Sortierung sieht sich eine binäre Suche das mittlere Element der Liste an und stellt dann die Frage: Ist das Objekt, nach dem Sie suchen, größer als das Objekt am aktuellen Punkt der Liste? Wenn das der Fall ist, wissen Sie, dass sich das Zielobjekt bei einem Index befindet, der in der Liste irgendwo oberhalb des aktuellen Index liegt. Ist das nicht der Fall, muss sich das Objekt bei einem Index befinden, der kleiner als der aktuelle Index ist. Der Algorithmus für eine binäre Suche stellt diese Frage, bis er das Objekt gefunden hat. Im Vergleich dazu beginnt eine lineare Suche beim ersten Element in der Liste und prüft, ob das das Element ist, nach dem Sie suchen. Wenn es das nicht ist, geht sie zum nächsten Objekt in der Liste weiter. Diese Operation wird wiederholt, bis das Objekt in der Liste gefunden wird. 4.5 Eine verkette Liste (LinkedList) implementieren 161

23 Siehe auch Das Thema»LinkedList<T> Class«in der MSDN-Dokumentation. Links 4.6 Einen Werttyp erstellen, der auf null initialisiert werden kann Problem Sie haben eine Variable, die einen numerischen Typ hat und einen numerischen Wert festhalten soll, der aus einer Datenbank kommt. Die Datenbank liefert für diesen Wert eventuell null zurück. Sie brauchen eine einfache und saubere Möglichkeit, diesen numerischen Wert zu speichern, auch wenn null zurückgeliefert wird. Lösung Verwenden Sie einen null-fähigen Werttyp. Es gibt zwei Möglichkeiten, einen null-fähigen Werttyp zu erstellen. Die erste ist die Verwendung des Typ-Modifiers?: int? mydbint = null; Die zweite Möglichkeit ist die Verwendung des generischen Typs Nullable<T>: Nullable<int> mydbint = new Nullable<int>( ); Diskussion Im Prinzip sind die beiden folgenden Anweisungen äquivalent: int? mydbint = null; Nullable<int> mydbint = new Nullable<int>( ); In beiden Fällen wird mydbint als ein null-fähiger Typ betrachtet und auf null initialisiert. Ein null-fähiger Typ implementiert das Interface INullableValue, das zwei schreibgeschützte Properties enthält, HasValue und Value. Das Property HasValue liefert false zurück, wenn der null-fähige Typ auf null gesetzt ist. Andernfalls liefert es true zurück. Wenn HasValue true zurückliefert, können Sie auf das Property Value zugreifen, das den aktuell gespeicherten Wert für den null-fähigen Datentyp enthält. Wenn HasValue false zurückliefert und Sie versuchen, auf das Property Value zuzugreifen, wird eine Invalid- OperationException ausgelöst. Das liegt daran, dass das Property Value an diesem Punkt undefiniert ist. Außerdem kann ein null-fähiger Typ auf zwei Weisen estet werden. Erstens, indem man wie hier das Property HasValue nutzt: if (mydbint.hasvalue) Console.WriteLine("Hat einen Wert: " + mydbint.value); 162 Kapitel 4: Generics

24 Rechts else Console.WriteLine("Hat keinen Wert (NULL)"); Zweitens, indem man ihn mit null vergleicht: if (mydbint!= null) Console.WriteLine("Hat einen Wert: " + mydbint.value); else Console.WriteLine("Hat keinen Wert (NULL)"); Beide Methoden sind zulässig. Wenn ein null-fähiger Typ auf einen nicht-null-fähigen Typ gecastet wird, funktioniert der Cast wie normal, außer wenn der null-fähige Typ auf null gesetzt ist. In diesem Fall wird eine InvalidOperationException ausgelöst. Wenn ein nicht-null-fähiger Typ auf einen null-fähigen Typ gecastet wird, funktioniert der Cast wie gewöhnlich. Es wird nie eine InvalidOperationException ausgelöst, weil der nicht-null-fähige Typ nie null sein kann. Worauf man bei null-fähigen Typen allerdings achten muss, sind Vergleiche wie im folgenden Code: if (mytempdbint < 100) Console.WriteLine("myTempDBInt < 100"); else Console.WriteLine("myTempDBInt >= 100"); Hier wird der Text»myTempDBInt >= 100«angezeigt, wenn mytempdbint null ist, und das ist offensichtlich falsch. Um diesen Code zu reparieren, muss man prüfen, ob mytemp- DBInt gleich null ist. Wenn das nicht der Fall ist, kann die if-anweisung aus dem vorangehenden Codeblock ausgeführt werden: if (mytempdbint!= null) if (mytempdbint < 100) Console.WriteLine("myTempDBInt < 100"); else Console.WriteLine("myTempDBInt >= 100"); else // Hier null verarbeiten. Eine andere interessante Sache bei null-fähigen Typen ist, dass Sie sie wie gewöhnliche numerische Typen in Ausdrücken verwenden können: int? DBInt = 10; int Value = 2; int? Result = DBInt + Value; // Ergebnis == 12 Wenn in einem Ausdruck null-fähige Typen verwendet werden, ist das Ergebnis null, wenn ein null-fähiger Typ null ist. Aber wenn kein null-fähiger Typ null ist, wird der Ausdruck ausgeführt wie gewöhnlich. Wenn oben DBInt auf null gesetzt würde, wäre der in Result gespeicherte Wert also auch null. 4.6 Einen Werttyp erstellen, der auf null initialisiert werden kann 163

25 Siehe auch Die Themen»Nullable (generische Struktur)«und»Verwenden von auf NULL festlegbaren Typen«in der MSDN-Dokumentation. Links 4.7 Den Inhalt einer SortedList umkehren Problem Sie möchten den Inhalt einer SortedList umkehren können und sich dabei gleichzeitig die Möglichkeit bewahren, auf sie im Array- oder List-Stil zuzugreifen, den die Klasse SortedList und die generische Klasse SortedList<T> bieten. Weder SortedList noch SortedList<T> bieten eine direkte Möglichkeit dazu, ohne die Liste neu zu laden. Lösung Verwenden Sie die Klasse ReversibleSortedList<TKey,TValue>, die wir Ihnen hier vorstellen. ReversibleSortedList<TKey,TValue> basiert auf der ursprünglichen Klasse Sorted- List<TKey,TValue>. Das sorgt dafür, dass die alten Funktionalitäten bewahrt bleiben, Sie aber die zusätzliche Bonusfähigkeit erhalten, die Ordnung der Elemente der Liste einfach umkehren zu können. Nachdem wir eine ReversibleSortedList<TKey,TValue> instanziiert haben, bei der der Schlüssel ein int und der Wert ein string ist, wird eine Folge nicht sortierter Zahlen und ihrer Textdarstellungen in die Liste eingefügt. Dann werden diese Elemente ausgegeben. ReversibleSortedList<int, string> rsl = new ReversibleSortedList<int, string>( ); rsl.add(2, "2"); rsl.add(5, "5"); rsl.add(3, "3"); rsl.add(1, "1"); foreach (KeyValuePair<int, string> kvp in rsl) Debug.WriteLine("\t" + kvp.key + "\t" + kvp.value); Hier sehen Sie die Ausgabe für diese Liste, wenn sie in aufsteigender Folge (der Default) sortiert ist: Jetzt kehren wir die Sortierrichtung um, indem wir das SortDirection-Property der ReversibleSortedList auf Descending setzen. Dann wird die Methode Sort( ) aufgerufen, um die Liste in der neuen Sortierrichtung zu sortieren. Anschließend werden die Ergebnisse angezeigt. 164 Kapitel 4: Generics

26 Rechts // Sortierrichtung umkehren. rsl.comparer.sortdirection = ListSortDirection.Descending; // Die Liste neu sortieren. rsl.sort( ); foreach (KeyValuePair<int, string> kvp in rsl) Debug.WriteLine("\t" + kvp.key + "\t" + kvp.value); Die Ausgabe hat dieses Mal eine absteigende Reihenfolge: Wenn der Liste ein neues Element hinzugefügt wird, wird es gemäß der aktuellen Sortierrichtung eingefügt. Aber indem Sie einfach die Sortierrichtung ändern, nachdem alle Elemente hinzugefügt worden sind, können Sie die Sortierung der Liste intakt halten: rsl.add(4, "4"); foreach (KeyValuePair<int, string> kvp in rsl) Debug.WriteLine("\t" + kvp.key + "\t" + kvp.value); // Sortierrichtung ändern. rsl.comparer.sortdirection = ListSortDirection.Ascending; // Die Liste neu sortieren. rsl.sort( ); foreach (KeyValuePair<int, string> kvp in rsl) Debug.WriteLine("\t" + kvp.key + "\t" + kvp.value); Sie sehen, dass das neue Element bei aufsteigender und absteigender Sortierung am richtigen Platz sitzt: Den Inhalt einer SortedList umkehren 165

27 Das wird in der ReversibleSortedList<TKey,TValue> durch eine eingebettete Klasse namens SortDirectionComparer<T> bewirkt, die das Interface IComparer<T> implementiert. Diese Klasse werden Sie im Diskussionsabschnitt sehen, in dem die Klasse Reversible- SortedList<TKey,TValue> abgedruckt ist. Eine Klasse, die das Interface IComparer<T> implementiert, kann als Parameter an ReversibleSortedList<TKey,TValue> übergeben werden, um die Default-Sortierung zu überschreiben. Die Compare-Methode dieser IComparer<T>-Implementierung sieht folgendermaßen aus: public int Compare(T lhs, T rhs) int compareresult = lhs.tostring( ).CompareTo(rhs.ToString( )); // Wenn die Sortierrichtung DESC ist, Vergleich umkehren. if (SortDirection == ListSortDirection.Descending) compareresult *= -1; return compareresult; Die Methode Compare nutzt das SortDirection-Property von SortDirectionComparer<T>, um die Sortierrichtung der Elemente zu ermitteln. Dieses wird von ReversibleSortedList <TKey,TValue> auf einer internen Instanz von SortDirectionComparer<T> gesetzt. Das erfolgt, wenn das SortDirection-Property der Klasse ReversibleSortedList<TKey,TValue> im Konstruktor gesetzt wird: public ReversibleSortedList( ) this.keys = ReversibleSortedList<TKey, TValue>.emptyKeys; this.values = ReversibleSortedList<TKey, TValue>.emptyValues; this._size = 0; this._sortdirectioncomparer = new SortDirectionComparer<TKey>( ); this._currentsortdirection = this._sortdirectioncomparer.sortdirection; Das ermöglicht es, die Sortierrichtung jederzeit umzukehren, kümmert sich aber nicht darum, die Elemente neu zu sortieren, die sich bereits in der Liste befinden. Dazu fügt die Klasse ReversibleSortedList<TKey,TValue> eine neue Sort( )-Methode hinzu, die sich um die Neusortierung der Liste kümmert: public void Sort( ) // Prüfen, ob die Liste bereits richtig sortiert ist. if (this._currentsortdirection!= this._sortdirectioncomparer.sortdirection) // Die Arrays umkehren, da sie bereits beim Einfügen sortiert wurden. Array.Reverse(this.keys, 0, this._size); Array.Reverse(this.values, 0, this._size); // Die aktuelle Sortierrichtung setzen. this._currentsortdirection = this._sortdirectioncomparer.sortdirection; Links 166 Kapitel 4: Generics

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

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

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

Studentische Lösung zum Übungsblatt Nr. 7

Studentische Lösung zum Übungsblatt Nr. 7 Studentische Lösung zum Übungsblatt Nr. 7 Aufgabe 1) Dynamische Warteschlange public class UltimateOrderQueue private Order[] inhalt; private int hinten; // zeigt auf erstes freies Element private int

Mehr

Einführung in die Programmierung

Einführung in die Programmierung Technische Universität München WS 2003/2004 Institut für Informatik Prof. Dr. Christoph Zenger Testklausur Einführung in die Programmierung Probeklausur Java (Lösungsvorschlag) 1 Die Klasse ArrayList In

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

Java Einführung Collections

Java Einführung Collections Java Einführung Collections Inhalt dieser Einheit Behälterklassen, die in der Java API bereitgestellt werden Wiederholung Array Collections (Vector, List, Set) Map 2 Wiederholung Array a[0] a[1] a[2] a[3]...

Mehr

Zählen von Objekten einer bestimmten Klasse

Zählen von Objekten einer bestimmten Klasse Zählen von Objekten einer bestimmten Klasse Ziel, Inhalt Zur Übung versuchen wir eine Klasse zu schreiben, mit der es möglich ist Objekte einer bestimmten Klasse zu zählen. Wir werden den ++ und den --

Mehr

4 Aufzählungen und Listen erstellen

4 Aufzählungen und Listen erstellen 4 4 Aufzählungen und Listen erstellen Beim Strukturieren von Dokumenten und Inhalten stellen Listen und Aufzählungen wichtige Werkzeuge dar. Mit ihnen lässt sich so ziemlich alles sortieren, was auf einer

Mehr

Einfache Arrays. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung

Einfache Arrays. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung Annabelle Klarl Zentralübung zur Vorlesung Einführung in die Informatik: http://www.pst.ifi.lmu.de/lehre/wise-13-14/infoeinf WS13/14 Action required now 1. Smartphone: installiere die App "socrative student"

Mehr

1 topologisches Sortieren

1 topologisches Sortieren Wolfgang Hönig / Andreas Ecke WS 09/0 topologisches Sortieren. Überblick. Solange noch Knoten vorhanden: a) Suche Knoten v, zu dem keine Kante führt (Falls nicht vorhanden keine topologische Sortierung

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

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag Ludwig-Maximilians-Universität München WS 2015/16 Institut für Informatik Übungsblatt 9 Prof. Dr. R. Hennicker, A. Klarl Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung:

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

Folge 19 - Bäume. 19.1 Binärbäume - Allgemeines. Grundlagen: Ulrich Helmich: Informatik 2 mit BlueJ - Ein Kurs für die Stufe 12

Folge 19 - Bäume. 19.1 Binärbäume - Allgemeines. Grundlagen: Ulrich Helmich: Informatik 2 mit BlueJ - Ein Kurs für die Stufe 12 Grundlagen: Folge 19 - Bäume 19.1 Binärbäume - Allgemeines Unter Bäumen versteht man in der Informatik Datenstrukturen, bei denen jedes Element mindestens zwei Nachfolger hat. Bereits in der Folge 17 haben

Mehr

Übungen 19.01.2012 Programmieren 1 Felix Rohrer. Übungen

Übungen 19.01.2012 Programmieren 1 Felix Rohrer. Übungen Übungen if / else / else if... 2... 2 Aufgabe 2:... 2 Aufgabe 3:... 2 Aufgabe 4:... 2 Aufgabe 5:... 2 Aufgabe 6:... 2 Aufgabe 7:... 3 Aufgabe 8:... 3 Aufgabe 9:... 3 Aufgabe 10:... 3 switch... 4... 4 Aufgabe

Mehr

Folge 18 - Vererbung

Folge 18 - Vererbung Workshop Folge 18 - Vererbung 18.1 Ein einfacher Fall der Vererbung Schritt 1 - Vorbereitungen Besorgen Sie sich - vielleicht aus einer der Übungen der Folge 17 - ein fertiges und lauffähiges Listenprojekt,

Mehr

Javakurs zu Informatik I. Henning Heitkötter

Javakurs zu Informatik I. Henning Heitkötter Javakurs zu Informatik I Arrays vergleichen Implementieren Sie folgende Methode, die prüft, ob die Elemente der beiden Arrays an jeder Position übereinstimmen: public static boolean identisch(int[] a,

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

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren Lineargleichungssysteme: Additions-/ Subtraktionsverfahren W. Kippels 22. Februar 2014 Inhaltsverzeichnis 1 Einleitung 2 2 Lineargleichungssysteme zweiten Grades 2 3 Lineargleichungssysteme höheren als

Mehr

Erwin Grüner 09.02.2006

Erwin Grüner 09.02.2006 FB Psychologie Uni Marburg 09.02.2006 Themenübersicht Folgende Befehle stehen in R zur Verfügung: {}: Anweisungsblock if: Bedingte Anweisung switch: Fallunterscheidung repeat-schleife while-schleife for-schleife

Mehr

Über Arrays und verkettete Listen Listen in Delphi

Über Arrays und verkettete Listen Listen in Delphi Über Arrays und verkettete Listen Listen in Delphi Michael Puff mail@michael-puff.de 2010-03-26 Inhaltsverzeichnis Inhaltsverzeichnis 1 Einführung 3 2 Arrays 4 3 Einfach verkettete Listen 7 4 Doppelt verkettete

Mehr

Datenbanken Kapitel 2

Datenbanken Kapitel 2 Datenbanken Kapitel 2 1 Eine existierende Datenbank öffnen Eine Datenbank, die mit Microsoft Access erschaffen wurde, kann mit dem gleichen Programm auch wieder geladen werden: Die einfachste Methode ist,

Mehr

Modellierung und Programmierung 1

Modellierung und Programmierung 1 Modellierung und Programmierung 1 Prof. Dr. Sonja Prohaska Computational EvoDevo Group Institut für Informatik Universität Leipzig 19. November 2015 Gültigkeitsbereich (Scope) von Variablen { int m; {

Mehr

Outlook. sysplus.ch outlook - mail-grundlagen Seite 1/8. Mail-Grundlagen. Posteingang

Outlook. sysplus.ch outlook - mail-grundlagen Seite 1/8. Mail-Grundlagen. Posteingang sysplus.ch outlook - mail-grundlagen Seite 1/8 Outlook Mail-Grundlagen Posteingang Es gibt verschiedene Möglichkeiten, um zum Posteingang zu gelangen. Man kann links im Outlook-Fenster auf die Schaltfläche

Mehr

Primzahlen und RSA-Verschlüsselung

Primzahlen und RSA-Verschlüsselung Primzahlen und RSA-Verschlüsselung Michael Fütterer und Jonathan Zachhuber 1 Einiges zu Primzahlen Ein paar Definitionen: Wir bezeichnen mit Z die Menge der positiven und negativen ganzen Zahlen, also

Mehr

Große Übung Praktische Informatik 1

Große Übung Praktische Informatik 1 Große Übung Praktische Informatik 1 2005-12-08 fuessler@informatik.uni-mannheim.de http://www.informatik.uni-mannheim.de/pi4/people/fuessler 1: Announcements / Orga Weihnachtsklausur zählt als Übungsblatt,

Mehr

Software Engineering Klassendiagramme Assoziationen

Software Engineering Klassendiagramme Assoziationen Software Engineering Klassendiagramme Assoziationen Prof. Adrian A. Müller, PMP, PSM 1, CSM Fachbereich Informatik und Mikrosystemtechnik 1 Lesen von Multiplizitäten (1) Multiplizitäten werden folgendermaßen

Mehr

Institut für Programmierung und Reaktive Systeme 25. August 2014. Programmier-Labor. 04. + 05. Übungsblatt. int binarysearch(int[] a, int x),

Institut für Programmierung und Reaktive Systeme 25. August 2014. Programmier-Labor. 04. + 05. Übungsblatt. int binarysearch(int[] a, int x), Technische Universität Braunschweig Dr. Werner Struckmann Institut für Programmierung und Reaktive Systeme 25. August 2014 Programmier-Labor 04. + 05. Übungsblatt Aufgabe 21: a) Schreiben Sie eine Methode

Mehr

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom 21.10.2013b

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom 21.10.2013b AGROPLUS Buchhaltung Daten-Server und Sicherheitskopie Version vom 21.10.2013b 3a) Der Daten-Server Modus und der Tresor Der Daten-Server ist eine Betriebsart welche dem Nutzer eine grosse Flexibilität

Mehr

Das Typsystem von Scala. L. Piepmeyer: Funktionale Programmierung - Das Typsystem von Scala

Das Typsystem von Scala. L. Piepmeyer: Funktionale Programmierung - Das Typsystem von Scala Das Typsystem von Scala 1 Eigenschaften Das Typsystem von Scala ist statisch, implizit und sicher 2 Nichts Primitives Alles ist ein Objekt, es gibt keine primitiven Datentypen scala> 42.hashCode() res0:

Mehr

M. Graefenhan 2000-12-07. Übungen zu C. Blatt 3. Musterlösung

M. Graefenhan 2000-12-07. Übungen zu C. Blatt 3. Musterlösung M. Graefenhan 2000-12-07 Aufgabe Lösungsweg Übungen zu C Blatt 3 Musterlösung Schreiben Sie ein Programm, das die Häufigkeit von Zeichen in einem eingelesenen String feststellt. Benutzen Sie dazu ein zweidimensionales

Mehr

Anleitung über den Umgang mit Schildern

Anleitung über den Umgang mit Schildern Anleitung über den Umgang mit Schildern -Vorwort -Wo bekommt man Schilder? -Wo und wie speichert man die Schilder? -Wie füge ich die Schilder in meinen Track ein? -Welche Bauteile kann man noch für Schilder

Mehr

1. Adressen für den Serienversand (Briefe Katalogdruck Werbung/Anfrage ) auswählen. Die Auswahl kann gespeichert werden.

1. Adressen für den Serienversand (Briefe Katalogdruck Werbung/Anfrage ) auswählen. Die Auswahl kann gespeichert werden. Der Serienversand Was kann man mit der Maske Serienversand machen? 1. Adressen für den Serienversand (Briefe Katalogdruck Werbung/Anfrage ) auswählen. Die Auswahl kann gespeichert werden. 2. Adressen auswählen,

Mehr

Kapitel 4 Die Datenbank Kuchenbestellung Seite 1

Kapitel 4 Die Datenbank Kuchenbestellung Seite 1 Kapitel 4 Die Datenbank Kuchenbestellung Seite 1 4 Die Datenbank Kuchenbestellung In diesem Kapitel werde ich die Theorie aus Kapitel 2 Die Datenbank Buchausleihe an Hand einer weiteren Datenbank Kuchenbestellung

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

AutoCAD 2007 - Dienstprogramm zur Lizenzübertragung

AutoCAD 2007 - Dienstprogramm zur Lizenzübertragung AutoCAD 2007 - Dienstprogramm zur Lizenzübertragung Problem: Um AutoCAD abwechselnd auf mehreren Rechnern einsetzen zu können konnte man bis AutoCAD 2000 einfach den Dongle umstecken. Seit AutoCAD 2000i

Mehr

Zwischenablage (Bilder, Texte,...)

Zwischenablage (Bilder, Texte,...) Zwischenablage was ist das? Informationen über. die Bedeutung der Windows-Zwischenablage Kopieren und Einfügen mit der Zwischenablage Vermeiden von Fehlern beim Arbeiten mit der Zwischenablage Bei diesen

Mehr

HANDBUCH PHOENIX II - DOKUMENTENVERWALTUNG

HANDBUCH PHOENIX II - DOKUMENTENVERWALTUNG it4sport GmbH HANDBUCH PHOENIX II - DOKUMENTENVERWALTUNG Stand 10.07.2014 Version 2.0 1. INHALTSVERZEICHNIS 2. Abbildungsverzeichnis... 3 3. Dokumentenumfang... 4 4. Dokumente anzeigen... 5 4.1 Dokumente

Mehr

Daten-Synchronisation zwischen dem ZDV-Webmailer und Outlook (2002-2007) Zentrum für Datenverarbeitung der Universität Tübingen

Daten-Synchronisation zwischen dem ZDV-Webmailer und Outlook (2002-2007) Zentrum für Datenverarbeitung der Universität Tübingen Daten-Synchronisation zwischen dem ZDV-Webmailer und Outlook (2002-2007) Zentrum für Datenverarbeitung der Universität Tübingen Inhalt 1. Die Funambol Software... 3 2. Download und Installation... 3 3.

Mehr

5. Tutorium zu Programmieren

5. Tutorium zu Programmieren 5. Tutorium zu Programmieren Dennis Ewert Gruppe 6 Universität Karlsruhe Institut für Programmstrukturen und Datenorganisation (IPD) Lehrstuhl Programmierparadigmen WS 2008/2009 c 2008 by IPD Snelting

Mehr

Typumwandlungen bei Referenztypen

Typumwandlungen bei Referenztypen Typumwandlungen bei Referenztypen Genau wie es bei einfachen Typen Typumwandlungen gibt, gibt es auch bei Referenztypen Umwandlungen von einem Referenztypen in einen anderen Referenztypen, die wie bei

Mehr

Handbuch für Redakteure

Handbuch für Redakteure Handbuch für Redakteure Erste Schritte... 1 Artikel erstellen... 2 Artikelinhalt bearbeiten... 3 Artikel bearbeiten... 3 Grunddaten ändern... 5 Weitere Artikeleigenschaften... 5 Der WYSIWYG-Editor... 6

Mehr

Suchbäume. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung

Suchbäume. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung Suchbäume Annabelle Klarl Zentralübung zur Vorlesung Einführung in die Informatik: http://www.pst.ifi.lmu.de/lehre/wise-13-14/infoeinf WS13/14 Action required now 1. Smartphone: installiere die App "socrative

Mehr

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3 Handbuch Fischertechnik-Einzelteiltabelle V3.7.3 von Markus Mack Stand: Samstag, 17. April 2004 Inhaltsverzeichnis 1. Systemvorraussetzungen...3 2. Installation und Start...3 3. Anpassen der Tabelle...3

Mehr

5. Abstrakte Klassen. Beispiel (3) Abstrakte Klasse. Beispiel (2) Angenommen, wir wollen die folgende Klassenhierarchie implementieren:

5. Abstrakte Klassen. Beispiel (3) Abstrakte Klasse. Beispiel (2) Angenommen, wir wollen die folgende Klassenhierarchie implementieren: 5. Abstrakte Klassen Beispiel 5. Abstrakte Klassen 5. Abstrakte Klassen Beispiel Beispiel (3) Angenommen, wir wollen die folgende Klassenhierarchie implementieren: Probleme des Implementierungsvorschlags:

Mehr

S/W mit PhotoLine. Inhaltsverzeichnis. PhotoLine

S/W mit PhotoLine. Inhaltsverzeichnis. PhotoLine PhotoLine S/W mit PhotoLine Erstellt mit Version 16.11 Ich liebe Schwarzweiß-Bilder und schaue mir neidisch die Meisterwerke an, die andere Fotografen zustande bringen. Schon lange versuche ich, auch so

Mehr

Rundung und Casting von Zahlen

Rundung und Casting von Zahlen W E R K S T A T T Rundung und Casting von Zahlen Intrexx 7.0 1. Einleitung In diesem Werkstattbeitrag erfahren Sie, wie Zahlenwerte speziell in Velocity, aber auch in Groovy, gerundet werden können. Für

Mehr

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag Ludwig-Maximilians-Universität München WS 2015/16 Institut für Informatik Übungsblatt 13 Prof. Dr. R. Hennicker, A. Klarl Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung:

Mehr

Institut für Programmierung und Reaktive Systeme 26. April 2013. Programmieren II. 10. Übungsblatt

Institut für Programmierung und Reaktive Systeme 26. April 2013. Programmieren II. 10. Übungsblatt Technische Universität Braunschweig Dr. Werner Struckmann Institut für Programmierung und Reaktive Systeme 26. April 2013 Programmieren II 10. Übungsblatt Hinweis: Insgesamt werden in diesem Semester fünf

Mehr

Job-Management simpel und klar (Einsätze, Aufträge, Lohn und Rechnung verwalten)

Job-Management simpel und klar (Einsätze, Aufträge, Lohn und Rechnung verwalten) data KUBLI... JobMan Bildbeschreibung Job-Management simpel und klar (Einsätze, Aufträge, Lohn und Rechnung verwalten) In der Folge einige Bilder des laufenden Programms... Das Willkommensfenster und Datenbindungstool.

Mehr

Objektorientierte Programmierung

Objektorientierte Programmierung Universität der Bundeswehr Fakultät für Informatik Institut 2 Priv.-Doz. Dr. Lothar Schmitz FT 2006 Zusatzaufgaben Lösungsvorschlag Objektorientierte Programmierung Lösung 22 (Java und UML-Klassendiagramm)

Mehr

Java 7. Elmar Fuchs Grundlagen Programmierung. 1. Ausgabe, Dezember 2011 JAV7

Java 7. Elmar Fuchs Grundlagen Programmierung. 1. Ausgabe, Dezember 2011 JAV7 Java 7 Elmar Fuchs Grundlagen Programmierung 1. Ausgabe, Dezember 2011 JAV7 5 Java 7 - Grundlagen Programmierung 5 Kontrollstrukturen In diesem Kapitel erfahren Sie wie Sie die Ausführung von von Bedingungen

Mehr

Objektorientierte Programmierung mit C++ Vector und List

Objektorientierte Programmierung mit C++ Vector und List Vector und List Ziel, Inhalt Wir lernen die Klassen vector und list aus der Standard-C++ Library kennen und anwenden. In einer Übung wenden wir diese Klassen an um einen Medienshop (CD s und Bücher) zu

Mehr

Java Kurs für Anfänger Einheit 4 Klassen und Objekte

Java Kurs für Anfänger Einheit 4 Klassen und Objekte Java Kurs für Anfänger Einheit 4 Klassen und Ludwig-Maximilians-Universität München (Institut für Informatik: Programmierung und Softwaretechnik von Prof.Wirsing) 13. Juni 2009 Inhaltsverzeichnis klasse

Mehr

Fachgebiet Informationssysteme Prof. Dr.-Ing. N. Fuhr. Programmierung Prof. Dr.-Ing. Nobert Fuhr. Übungsblatt Nr. 6

Fachgebiet Informationssysteme Prof. Dr.-Ing. N. Fuhr. Programmierung Prof. Dr.-Ing. Nobert Fuhr. Übungsblatt Nr. 6 Gudrun Fischer Sascha Kriewel programmierung@is.informatik.uni-duisburg.de Anmeldung zur Klausur! Übungsblatt Nr. 6 Um an der Klausur teilzunehmen, müssen sich Studierende der angewandten Informatik in

Mehr

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen: VBA Programmierung mit Excel Schleifen 1/6 Erweiterung der Aufgabe Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen: Es müssen also 11 (B L) x 35 = 385 Zellen berücksichtigt

Mehr

Systeme 1. Kapitel 6. Nebenläufigkeit und wechselseitiger Ausschluss

Systeme 1. Kapitel 6. Nebenläufigkeit und wechselseitiger Ausschluss Systeme 1 Kapitel 6 Nebenläufigkeit und wechselseitiger Ausschluss Threads Die Adressräume verschiedener Prozesse sind getrennt und geschützt gegen den Zugriff anderer Prozesse. Threads sind leichtgewichtige

Mehr

Lineare Differentialgleichungen erster Ordnung erkennen

Lineare Differentialgleichungen erster Ordnung erkennen Lineare Differentialgleichungen erster Ordnung In diesem Kapitel... Erkennen, wie Differentialgleichungen erster Ordnung aussehen en für Differentialgleichungen erster Ordnung und ohne -Terme finden Die

Mehr

Datenbanken Microsoft Access 2010

Datenbanken Microsoft Access 2010 Datenbanken Microsoft Access 2010 Abfragen Mithilfe von Abfragen kann ich bestimmte Informationen aus einer/mehrerer Tabellen auswählen und nur diese anzeigen lassen die Daten einer/mehrerer Tabellen sortieren

Mehr

Geld Verdienen im Internet leicht gemacht

Geld Verdienen im Internet leicht gemacht Geld Verdienen im Internet leicht gemacht Hallo, Sie haben sich dieses E-book wahrscheinlich herunter geladen, weil Sie gerne lernen würden wie sie im Internet Geld verdienen können, oder? Denn genau das

Mehr

Kurzanleitung fu r Clubbeauftragte zur Pflege der Mitgliederdaten im Mitgliederbereich

Kurzanleitung fu r Clubbeauftragte zur Pflege der Mitgliederdaten im Mitgliederbereich Kurzanleitung fu r Clubbeauftragte zur Pflege der Mitgliederdaten im Mitgliederbereich Mitgliederbereich (Version 1.0) Bitte loggen Sie sich in den Mitgliederbereich mit den Ihnen bekannten Zugangsdaten

Mehr

Jederzeit Ordnung halten

Jederzeit Ordnung halten Kapitel Jederzeit Ordnung halten 6 auf Ihrem Mac In diesem Buch war bereits einige Male vom Finder die Rede. Dieses Kapitel wird sich nun ausführlich diesem so wichtigen Programm widmen. Sie werden das

Mehr

In vergleichsbasierten Suchbäumen wird nicht in Schlüssel hineingeschaut.

In vergleichsbasierten Suchbäumen wird nicht in Schlüssel hineingeschaut. Binäre Suchbäume Tries (Folie 182, Seite 58 im Skript) In vergleichsbasierten Suchbäumen wird nicht in Schlüssel hineingeschaut. In Tries entspricht die ite Verzweigung dem iten Zeichen des Schlüssels.

Mehr

Konzepte der Informatik

Konzepte der Informatik Konzepte der Informatik Vorkurs Informatik zum WS 2011/2012 26.09. - 30.09.2011 17.10. - 21.10.2011 Dr. Werner Struckmann / Christoph Peltz Stark angelehnt an Kapitel 1 aus "Abenteuer Informatik" von Jens

Mehr

104 WebUntis -Dokumentation

104 WebUntis -Dokumentation 104 WebUntis -Dokumentation 4.1.9.2 Das elektronische Klassenbuch im Betrieb Lehrer Aufruf Melden Sie sich mit Ihrem Benutzernamen und Ihrem Passwort am System an. Unter den aktuellen Tagesmeldungen erscheint

Mehr

Stammdatenanlage über den Einrichtungsassistenten

Stammdatenanlage über den Einrichtungsassistenten Stammdatenanlage über den Einrichtungsassistenten Schritt für Schritt zur fertig eingerichteten Hotelverwaltung mit dem Einrichtungsassistenten Bitte bereiten Sie sich, bevor Sie starten, mit der Checkliste

Mehr

5. Abstrakte Klassen

5. Abstrakte Klassen 5. Abstrakte Klassen Beispiel 5. Abstrakte Klassen Angenommen, wir wollen die folgende Klassenhierarchie implementieren: Vogel Amsel Drossel Fink Peter Becker, Programiersprache Java FH Bonn-Rhein-Sieg,

Mehr

Handbuch. NAFI Online-Spezial. Kunden- / Datenverwaltung. 1. Auflage. (Stand: 24.09.2014)

Handbuch. NAFI Online-Spezial. Kunden- / Datenverwaltung. 1. Auflage. (Stand: 24.09.2014) Handbuch NAFI Online-Spezial 1. Auflage (Stand: 24.09.2014) Copyright 2016 by NAFI GmbH Unerlaubte Vervielfältigungen sind untersagt! Inhaltsangabe Einleitung... 3 Kundenauswahl... 3 Kunde hinzufügen...

Mehr

Lehrer: Einschreibemethoden

Lehrer: Einschreibemethoden Lehrer: Einschreibemethoden Einschreibemethoden Für die Einschreibung in Ihren Kurs gibt es unterschiedliche Methoden. Sie können die Schüler über die Liste eingeschriebene Nutzer Ihrem Kurs zuweisen oder

Mehr

Professionelle Seminare im Bereich MS-Office

Professionelle Seminare im Bereich MS-Office Der Name BEREICH.VERSCHIEBEN() ist etwas unglücklich gewählt. Man kann mit der Funktion Bereiche zwar verschieben, man kann Bereiche aber auch verkleinern oder vergrößern. Besser wäre es, die Funktion

Mehr

Hilfedatei der Oden$-Börse Stand Juni 2014

Hilfedatei der Oden$-Börse Stand Juni 2014 Hilfedatei der Oden$-Börse Stand Juni 2014 Inhalt 1. Einleitung... 2 2. Die Anmeldung... 2 2.1 Die Erstregistrierung... 3 2.2 Die Mitgliedsnummer anfordern... 4 3. Die Funktionen für Nutzer... 5 3.1 Arbeiten

Mehr

Benutzerhandbuch - Elterliche Kontrolle

Benutzerhandbuch - Elterliche Kontrolle Benutzerhandbuch - Elterliche Kontrolle Verzeichnis Was ist die mymaga-startseite? 1. erste Anmeldung - Administrator 2. schnittstelle 2.1 Administrator - Hautbildschirm 2.2 Administrator - rechtes Menü

Mehr

Kundenspezifische Preise im Shop WyRu Online-Shop

Kundenspezifische Preise im Shop WyRu Online-Shop Kundenspezifische Preise im Shop WyRu Online-Shop Team WyRu Christian Wyk / Günter Rubik SCS Bürocenter B1, A-2334 Vösendorf Internet http://www.wyru.at Kundenspezifische Preise sind ein Feature des WyRu

Mehr

FH-SY Chapter 2.4 - Version 3 - FH-SY.NET - FAQ -

FH-SY Chapter 2.4 - Version 3 - FH-SY.NET - FAQ - FH-SY Chapter 2.4 - Version 3 - FH-SY.NET - FAQ - Version vom 02.02.2010 Inhaltsverzeichnis 1. KANN ICH BEI EINER EIGENEN LEKTION NACHTRÄGLICH NOCH NEUE LERNINHALTE ( WAS WURDE BEHANDELT? ) EINFÜGEN?...

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

L10N-Manager 3. Netzwerktreffen der Hochschulübersetzer/i nnen Mannheim 10. Mai 2016

L10N-Manager 3. Netzwerktreffen der Hochschulübersetzer/i nnen Mannheim 10. Mai 2016 L10N-Manager 3. Netzwerktreffen der Hochschulübersetzer/i nnen Mannheim 10. Mai 2016 Referentin: Dr. Kelly Neudorfer Universität Hohenheim Was wir jetzt besprechen werden ist eine Frage, mit denen viele

Mehr

U08 Entwurfsmuster (II)

U08 Entwurfsmuster (II) U08 Entwurfsmuster (II) Inhalt der Übung Diskussion und Implementierung von Entwurfsmustern Übungsaufgaben Aufgabe 1 (Queue) Gegeben ist das folgende Analysemodell einer Warteschlange (Queue): Eine Warteschlange

Mehr

Erstellen der Barcode-Etiketten:

Erstellen der Barcode-Etiketten: Erstellen der Barcode-Etiketten: 1.) Zuerst muss die Schriftart Code-39-Logitogo installiert werden! Das ist eine einmalige Sache und muss nicht zu jeder Börse gemacht werden! Dazu speichert man zunächst

Mehr

Erstellen von x-y-diagrammen in OpenOffice.calc

Erstellen von x-y-diagrammen in OpenOffice.calc Erstellen von x-y-diagrammen in OpenOffice.calc In dieser kleinen Anleitung geht es nur darum, aus einer bestehenden Tabelle ein x-y-diagramm zu erzeugen. D.h. es müssen in der Tabelle mindestens zwei

Mehr

Java: Vererbung. Teil 3: super() www.informatikzentrale.de

Java: Vererbung. Teil 3: super() www.informatikzentrale.de Java: Vererbung Teil 3: super() Konstruktor und Vererbung Kindklasse ruft SELBSTSTÄNDIG und IMMER zuerst den Konstruktor der Elternklasse auf! Konstruktor und Vererbung Kindklasse ruft SELBSTSTÄNDIG und

Mehr

Anleitung zu GermanLegal 1.3

Anleitung zu GermanLegal 1.3 Anleitung zu GermanLegal 1.3 Was sind permanente Rechnungen? In Deutschland macht man sich normalerweise über solche Dinge keine Gedanken. Wer als ISP WHMCS nutzt, muss dies aber. WHMCS erlaubt ungehinderte

Mehr

Algorithmen und Datenstrukturen

Algorithmen und Datenstrukturen Algorithmen und Datenstrukturen Tafelübung 04 Referenzen, Overloading, Klassen(hierarchien) Clemens Lang T2 18. Mai 2010 14:00 16:00, 00.152 Tafelübung zu AuD 1/13 Organisatorisches Nächster Übungstermin

Mehr

Klausur C-Programmierung / 15.02.2014 / Klingebiel / 60 Minuten / 60 Punkte

Klausur C-Programmierung / 15.02.2014 / Klingebiel / 60 Minuten / 60 Punkte Klausur C-Programmierung / 15.02.2014 / Klingebiel / 60 Minuten / 60 Punkte Musterlösung 1. Aufgabe (5 Punkte) Im folgenden Programmcode sind einige Fehler enthalten. Finden und markieren Sie mindestens

Mehr

Bereich METIS (Texte im Internet) Zählmarkenrecherche

Bereich METIS (Texte im Internet) Zählmarkenrecherche Bereich METIS (Texte im Internet) Zählmarkenrecherche Über die Zählmarkenrecherche kann man nach der Eingabe des Privaten Identifikationscodes einer bestimmten Zählmarke, 1. Informationen zu dieser Zählmarke

Mehr

Excel Auswertungen in XAuftrag / XFibu

Excel Auswertungen in XAuftrag / XFibu 1 Excel Auswertungen in XAuftrag / XFibu Im Folgenden wird kurz beschrieben, wie Anwender die Sicherheitseinstellungen in Excel Auswertungen anpassen können. Sicherheitseinstellungen verhindern, dass Makros

Mehr

2. Im Admin Bereich drücken Sie bitte auf den roten Button Webseite bearbeiten, sodass Sie in den Bearbeitungsbereich Ihrer Homepage gelangen.

2. Im Admin Bereich drücken Sie bitte auf den roten Button Webseite bearbeiten, sodass Sie in den Bearbeitungsbereich Ihrer Homepage gelangen. Bildergalerie einfügen Wenn Sie eine Vielzahl an Bildern zu einem Thema auf Ihre Homepage stellen möchten, steht Ihnen bei Schmetterling Quadra das Modul Bildergalerie zur Verfügung. Ihre Kunden können

Mehr

Anton Ochsenkühn. amac BUCH VERLAG. Ecxel 2016. für Mac. amac-buch Verlag

Anton Ochsenkühn. amac BUCH VERLAG. Ecxel 2016. für Mac. amac-buch Verlag Anton Ochsenkühn amac BUCH VERLAG Ecxel 2016 für Mac amac-buch Verlag 2 Word-Dokumentenkatalog! Zudem können unterhalb von Neu noch Zuletzt verwendet eingeblendet werden. Damit hat der Anwender einen sehr

Mehr

Einführung in die Programmierung

Einführung in die Programmierung : Inhalt Einführung in die Programmierung Wintersemester 2008/09 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund - mit / ohne Parameter - mit / ohne Rückgabewerte

Mehr

Belichtung mit Tonwertkorrektur verbessern

Belichtung mit Tonwertkorrektur verbessern Belichtung mit Tonwertkorrektur verbessern Die meisten Digitalfotos müssen vor dem Ausdruck bearbeitet werden: Helligkeit und Kontrast sollten für ein besseres Ergebnis reguliert werden. Die Tonwertkorrektur

Mehr

Einrichten einer mehrsprachigen Webseite mit Joomla (3.3.6)

Einrichten einer mehrsprachigen Webseite mit Joomla (3.3.6) Einrichten einer mehrsprachigen Webseite mit Joomla (3.3.6) 1. Loggen Sie sich im Administratorbereich ein und gehen Sie auf Extension > Extension Manager 2. Wählen Sie Install languages 3. Klicken Sie

Mehr

Tipps und Tricks zu den Updates

Tipps und Tricks zu den Updates Tipps und Tricks zu den Updates Grundsätzlich können Sie Updates immer auf 2 Wegen herunterladen, zum einen direkt über unsere Internetseite, zum anderen aus unserer email zu einem aktuellen Update. Wenn

Mehr

Persönliche Zukunftsplanung mit Menschen, denen nicht zugetraut wird, dass sie für sich selbst sprechen können Von Susanne Göbel und Josef Ströbl

Persönliche Zukunftsplanung mit Menschen, denen nicht zugetraut wird, dass sie für sich selbst sprechen können Von Susanne Göbel und Josef Ströbl Persönliche Zukunftsplanung mit Menschen, denen nicht zugetraut Von Susanne Göbel und Josef Ströbl Die Ideen der Persönlichen Zukunftsplanung stammen aus Nordamerika. Dort werden Zukunftsplanungen schon

Mehr

OECD Programme for International Student Assessment PISA 2000. Lösungen der Beispielaufgaben aus dem Mathematiktest. Deutschland

OECD Programme for International Student Assessment PISA 2000. Lösungen der Beispielaufgaben aus dem Mathematiktest. Deutschland OECD Programme for International Student Assessment Deutschland PISA 2000 Lösungen der Beispielaufgaben aus dem Mathematiktest Beispielaufgaben PISA-Hauptstudie 2000 Seite 3 UNIT ÄPFEL Beispielaufgaben

Mehr

Flash Videos einbinden

Flash Videos einbinden Flash Videos einbinden Im Kapitel Videos einbinden ( - ) haben Sie gesehen, wie man einfach und ohne Zusatzprogramme kleine Videoclips auf seiner einbinden kann. Ich persönlich würde jedem dieses Verfahren

Mehr

EndTermTest PROGALGO WS1516 A

EndTermTest PROGALGO WS1516 A EndTermTest PROGALGO WS1516 A 14.1.2016 Name:................. UID:.................. PC-Nr:................ Beachten Sie: Lesen Sie erst die Angaben aufmerksam, genau und vollständig. Die Verwendung von

Mehr

Grundlagen der Theoretischen Informatik, SoSe 2008

Grundlagen der Theoretischen Informatik, SoSe 2008 1. Aufgabenblatt zur Vorlesung Grundlagen der Theoretischen Informatik, SoSe 2008 (Dr. Frank Hoffmann) Lösung von Manuel Jain und Benjamin Bortfeldt Aufgabe 2 Zustandsdiagramme (6 Punkte, wird korrigiert)

Mehr

Dokumentenverwaltung im Internet

Dokumentenverwaltung im Internet Dokumentenverwaltung im Internet WS 09/10 mit: Thema: Workflow und Rollenverteilung im Backend Gruppe: DVI 10 Patrick Plaum und Kay Hofmann Inhalt 1. Benutzer und Benutzergruppen erstellen...2 1.1. Benutzergruppen...2

Mehr

Aufklappelemente anlegen

Aufklappelemente anlegen Aufklappelemente anlegen Dieses Dokument beschreibt die grundsätzliche Erstellung der Aufklappelemente in der mittleren und rechten Spalte. Login Melden Sie sich an der jeweiligen Website an, in dem Sie

Mehr

BEISPIELKLAUSUR Softwareentwicklung:

BEISPIELKLAUSUR Softwareentwicklung: Prof. Dr. Andreas Fink Institut für Informatik Fakultät für Wirtschafts- und Sozialwissenschaften Helmut-Schmidt-Universität / Universität der Bundeswehr Hamburg BEISPIELKLAUSUR Softwareentwicklung: Objektorientierte

Mehr