Schöner und Schneller: Statisches Typing mit Generics vs. Dynamisches Typing


Thomas Wölfer
Thomas Wölfer

22. November 2005


Solch einen Fall habe ich relativ oft: Es gibt eine Liste von Objekten unterschiedlicher Art (in meinem Fall sind das immer Singletons), und ich brauche die Instanz, die einen bestimmten Typ hat. (In meine Fall gehts immer darum die Instanz zu finden, die ein bestimmtes Interface unterstützt.)

Um das zu simulieren verwende ich hier im Beispiel einfach eine große Menge an Objekten von Typ (A) und ein einzelnes von Typ (B). Nach (B) wird dann gesucht. Die Liste sieht also in etwa wie folgt aus und wird für den Test so aufgefüllt:

private List<object> objects = new List<object>;
for (int i = 0; i < 500000; i++)
{
   objects.Add(
new Button());
}
objects.Add(
new NumericUpDown());

(Wie gesagt: Eigentlich müsste es sich um lauter unterschiedliche Typen handeln.) Mit den Möglichkeiten von .Net < 2.0 sieht eine entsprechende Funktion zum suchen einer bestimmten Instanz dann so aus:

private object FindDynamic(Type type)
{
   foreach (object o in dynamic)
   {
     if (type.IsAssignableFrom(o.GetType())) return o;
   }
   return null;
}

Der Aufruf der Funktion wird dann sehr unschön: Der gesuchte Typ kommt dreimal vor, und außerdem braucht man noch  einen Cast:

NumericUpDown result = FindDynamic(typeof(NumericUpDown)) as NumericUpDown;

Laufzeit im Beispiel: etwa 90 ms.

Mit .Net 2.0 und Generics kann man die Funktion zum finden so hinschreiben, das man nur noch RTTI und statisches typing verwendet - es braucht keine Reflections mehr:

private T Find<T>() where T:class
{
   foreach (object o in dynamic)
   {
      T result = o
as T;
      if (result != null) return result;
   }
   return null;
}

Laufzeit im Beispiel : < 70 ms

Die verbesserung der Performance ist aber eigentlich nicht der Hauptvorteil - der liegt vielmehr darin, wie der Aufruf der Funktion nun aussieht: Der ist nämlich deutlich hübscher:

NumericUpDown result = Find<NumericUpDown>();