Generic Collections

 
04 december 2007

Deze en volgende artikelen over .NET schrijf ik om mezelf iets uit te leggen. Het mes snijdt dan aan twee kanten : ik ben dan vrijwel genoodzaakt om het goed uit te zoeken en anderen kunnen er misschien ook nog wat aan hebben. Ik begin simpel : generic collections.

Stel ik wil waarden van het type string in een hashtable zetten met een key van het type integer :

Hashtable table = new Hashtable();
table.Add(1, "Naam");
table.Add(2, "Naam2");

Tijdens het programmeren voeg ik op een zeker moment per ongeluk een integer-waarde aan de hashtable toe :

table.Add(3, 1);

Het compileert, dus goed. Maar wat als ik de waarden uit die hashtable in een database tabel wil stoppen waarbij de waarden per se van het type string moet zijn omdat de kolom in de databasetabel alleen maar een string accepteert en geen integer?

Bij het itereren over de hashtable values, kom ik een ander probleem tegen :

foreach (string val in table.Values)
{
	Console.WriteLine("value = {0}", val);
}
Console.ReadLine();

De waarden waren van het type string in eerste instantie ,toch? Okay, blijkbaar heb ik ergens in de code een integer toegevoegd aan de hashtable want ik krijg een exception. Goed, dan zitten er string waarden en integer waarden in mijn hashtable. Dan maken we er objecten van die we gaan uitlezen :

foreach (Object val in table.Values)
{
	Console.WriteLine("value = {0}", val.ToString());
}
Console.ReadLine();

Works like a charm. Maar wat als ik zelf gemaakte objecten in de hashtable wil zetten?
Of wat dan ook? Stel je voor dat ik een foreach loopje moet schrijven voor ieder soort object dat ik in een hashtable wil zetten… Zou het niet veel handiger zijn wanneer ik bij het initiëren van een hashtable kan aangeven welk type value ik er in wil op slaan en dat ik me tijdens het programmeren daar aan moet houden? (Strongly typed)

Precies daarvoor zijn er generic collections.

Om het voorbeeld van de hashtable aan te houden. Stel, ik wil afdwingen dat ik alleen maar waarden van het type string aan de hashtable mag toevoegen. Hier zou ik mijn eigen hashtable class voor kunnen schrijven die alleen maar strings accepteert :

class MyHashtable : ICollection, IEnumerable
{
	private Hashtable _innertable = new Hashtable();
	public void Add(int key, string value)
	{
		_innertable.Add(key, value);
	}

	public string this[int key]
	{
		get {
			return (string)_innertable[key];
		}
	}
}

Wel lastig hierbij is, dat je de andere methods van je Interfaces (ICollection en IEnumerable) ook moet implementeren want je wilt natuurlijk wel dezelfde mogelijkheden voor je custom-hashtable als de hashtable van .NET. Om niet alle methods zelf te hoeven achterhalen welke geïmplementeerd moeten worden, heeft Visual Studio 2005 een mooie functie, namelijk “implement interface”.
Maar voor ieder type – string, integer, double, objecten, enz. – een eigen class maken is teveel werk, daarom maken we een generic class. Bij het instantiëren hiervan kun je aangeven welk type je gebruikt. Of om het moeilijk te zeggen :

Generic types zijn types die andere type namen gebruikt om ze te definiëren als een type.

Onze generic class :

class MyHashtable<T> : ICollection, IEnumerable
{
	private Hashtable _innertable = new Hashtable();	public void Add(int key, T value)
	{
		_innertable.Add(key, value);
	}

	public T this[int key]
	{
		get {
			return (T)_innertable[key];
		}
	}
}

Nu kunnen we een nieuwe hashtable aanmaken voor ieder type (string, int, objects, enzovoort) en toch dezelfde implementatie van de hashtable gebruiken. Bijkomend voordeel is dan ook nog eens type safety bij het instantiëren van de hashtable :

MyHashtable<string> table = new MyHashtable<string>();
table.Add(1, "Naam");
table.Add(2, 5);

Bij het compileren hiervan, komt een error naar voren. Deze geeft aan dat de hashtable alleen maar strings als waarde wil hebben. Zet in plaats van de string dus int neer en de compiler slikt alleen maar integers als value.


Werken met ?
Kijk dan bij onze mogelijkheden voor zowel starters als ervaren engineers.


Categorieën: Development

Tags: ,


Reacties (2)

  • Marco, dank voor je reactie :) Ben min of meer wel emotioneel gebonden aan de hastable :) Heb namelijk bij een klant van Sogyo gezeten en daar veel met perl en php gewerkt ;) dus vandaar!

    Geplaatst op 14 december 2007 om 13:36 Permalink

  • Marco Bosman schreef:

    Een mooi stukje :-) . Als je niet emotioneel gebonden bent aan het gebruik van de Hashtable zou je ook kunnen kijken naar de Dictionary welke reeds gebruik maakt van generics. Tenzij er een groot verschil is in performance tussen de Hashtable en de Dictionary natuurlijk (Heb hier nog geen onderzoek naar gedaan). Beide maken gebruik van key-value pairs.

    Geplaatst op 14 december 2007 om 10:22 Permalink

Trackback & Pingback (1)

  1. Van Sogyo lanceert corporate blog software-innovators.nl | Sogyo op 28 december 2007 at 10:56

    […] kun je verwachten? Hieronder een greep uit de recente postings: Extension methods in C# 3.0, Generic Collections, Enterprise Software Development: Confusion about Internal DSLs of […]