Site logo
Site logo
Programmieren aus Leidenschaft
Programmieren aus Leidenschaft

Array Listen und Generische Listen


Listen sind zweifellos ein tolle Sache. Listen sind wunderbar um Daten zu speichern, zu zählen, zu sortieren oder anderweitig zu verwenden. Leider sind Listen nicht so einfach wie es auf den ersten Blick scheint.
Das Instanzieren einer einfachen ArrayList ist recht einfach und unterscheidet sich nicht vom Instanzieren anderer Objekten.

ArrayList alist = new ArrayList();

Will man nun dieser Liste Elemente hinzufügen, gibt es dafür die ‚Add' Methode.

alist.Add("Hallo");
alist.Add("Welt");


Zwei neue Zeichenketten werden der Liste hinzugefügt. Das war leicht. Kann man aber der Liste auch andere Typen als Zeichenketten hinzufügen? Natürlich, auch das ist kein Problem. Fügen wir also eine Ganzzahl und eine Fließkommazahl hinzu.

alist.Add(1);
alist.Add(23.5f);


Jetzt ist der richtige Moment für Verwunderung. Zeichenketten und Zahlen in derselben Liste? Ja, das geht wirklich. Und man kann noch ganz andere Dinge hinzufügen. Versuchen wir es also mal mit etwas ungewöhnlichem, wie einem Thread.

Thread tr = new Thread(methode);
alist.Add(tr);


Auch das funktioniert. Natürlich sind solche Listen nicht unbedingt sinnvoll. Was passiert also, wenn der komplette Listeninhalt ausgegeben wird.

foreach ( Object obj in alist )
{
   Console.WriteLine(obj);
}


Diese Ausgabe funktioniert ebenfalls fehlerlos, ist nur beim Element des Thread wenig nützlich. Problematisch wird so eine Liste erst dann, wenn man die Summe aller Listenelemente berechnen will, oder alle Elemente auf einen anderen Datentyp konvertieren möchte. Solange sich nur Zahlen in der Liste befinden, ist es kein Problem. Stößt man hingegen auf Zeichenketten oder andere Datentypen sind die Probleme buchstäblich vorprogrammiert.
Eine ArrayList kann viele verschieden Datentypen aufnehmen, doch muss der Programmierer selbst dafür Sorge tragen, dassder Liste nur Elemente zugefügt werden, die auch fehlerlos verarbeitet werden können. Eine Liste die von vornherein auf einen bestimmten Datentype festgelegt ist, ist in den meisten Fällen sinnvoller. Dafür gibt es generische Listen.
Die Definition einer generischen Liste ist denkbar einfach:

List<string> namen = new Lis<string>t();

erzeugt eine Liste aus Zeichenketten

List<int> zahlen = new List<int>();

erzeugt eine Liste aus Ganzzahlen.

Diese Definition ist fest. Der Versuch artfremde Daten an die Liste anzuhängen wird vom Compiler verweigert. Man kann das Programm gar nicht erst erstellen. Dadurch minimiert sich auch die Gefahr, dass sich während der Nutzung des Programmmes Daten in die Liste einschleichen können, die dort nicht hinein gehören.

Diese zwei Befehle funktionieren nicht!

namen.Add(1);
zahlen.Add("Hallo");


Eine generische Liste kann also aus beliebigen Daten gleichen Typs bestehen, und natürlich auch aus Daten benutzerdefinierten Typs. Auch aus einer Klasse.

public class Person
{
   public string name;
   public string vorname;
}


Diese wenig spektakuläre Klasse hat nur zwei Felder, nämlich name und vorname. Auch auf get und set Methoden verzichten wir der Einfachheit halber komplett. Eine Liste mit Objekten dieser Klasse ist jetzt nicht viel anders, als in den zuvor gezeigten Beispielen.

List<Person> personen = new List<Person>();

Dieser Liste kann man jetzt nur Objekte der Klasse Person hinzufügen, diese Objekte muss man allerdings noch erstellen. Danach ist das Hinzufügen kein Problem mehr.

Person p = new Person();
p.vorname = "Max";
p.name = "Mustermann";

personen.Add(p);

Person i = new Person();
i.vorname = "Anna";
i.name = "Musterfrau";

personen.Add(i);


Zugegeben, diese Art eine Liste zu füllen ist etwas mühselig. Darum an dieser Stelle ein Beispiel wie es einfacher geht. Das hat zwar nicht mehr viel mit Listen zu tun aber es passt ideal zum Thema. Das Geheimnis liegt hier im Konstruktor der Person Klasse. Wir ändern unsere Klasse wie folgt:

class Person
{
   public string name;
   public string vorname;

   public Person ()
   {}

   public Person (string vorname, string name)
   {
      this.name = name;
      this.vorname = vorname;
   }
}


Durch den erweiterten Konstruktor können jetzt beim Instanzieren der Klasse sofort Werte mitgegeben werden.

Person h = new Person("Hans", "Meier");
personen.Add(h);


Auch diese Vorgehensweise lässt sich weiter vereinfachen. Das Erstellen einer Person und das Hinzufügen dieser zur Personenliste, ist in einer Programmzeile möglich.

personen.Add(new Person("Holger", "Schmitt"));

Die Benutzung einer generischen Liste bringt noch weitere Vorteile: Da man mit einer Liste gleicher Objekte arbeitet, ist die foreach-Schleife hier bestens angebracht um die komplette Liste auszugeben.

foreach (Person per in personen)
{
   Console.WriteLine("{0} {1}", per.vorname, per.name);
}


Zusammenfassend läst sich sagen: Generische Listen sind nicht nur sicherer in der Handhabung, sie benötigen auch viel weniger Systemresourcen.