Hi,
das ganze ist etwas kompliziert zu erklären. Deshalb wird der Post etwas lang und unverständlich. 🙂
Erstmal muss man sich klar machen wie ein Switch funktioniert: es ist eine Sprungtabelle. Das heißt, man springt einfach um eine bestimmte Länge nach vorne (im IL) und ist dann bei der richtigen Instruktion. Natürlich kann man nicht beliebig weit springen, sondern der Compiler benutzt Sprünge ab 0. Angenommen man halt also drei Integer-Cases 0,1,2 ist die Welt schön und gut. Angenommen man hat die Cases 3,4,5 muss der Compiler erst -3 machen. Jetzt gibt es beliebig komplexe Cases die den Compiler verrückt machen, man stelle sich die Cases 32,42,1052 vor. 🙂
Wir haben aber Strings! Also muss der Compiler richtig tricksen. Was er macht ist folgendes: vor dem Switch benutzt er heimlich ein Dictionary<string,int>, packt dort die Cases und die Sprünge (0,1,2,...) rein.
Die IL das Ä sieht dann so aus:
L_0018: dup
L_0019: ldstr "\u00c4" // Das Ä
L_001e: ldc.i4.0 // Die 0
L_001f: call instance void [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::Add(!0, !1)
Die Sprungtabelle ist dann:
L_0079: switch (L_0098, L_00a0, L_00a8, L_00b0, L_00b8, L_00c0) // Hier steht: springe zu Label L_0098 im Falle 0, L_00a0 im Falle 1, ...
L_0096: br.s L_00c8 // Hier ist Sprung zu default
L_0098: ldstr "AE" // Fall 0 (Ä)
L_009d: stloc.0
L_009e: br.s L_00cc // Springe zum Ende des Switches
usw.
Das string-Switch ist also eigentlich eine Lüge (unabhängig von Debug oder Release)! Das können wir auch selbst mit einem Dictionary, und man spart sich das zusätzliche Switch am Ende.
Warum also Switch? Na ja, normalerweise ist ein Switch zugar schneller als entsprechende Ifs! Wenn man also z.B. ein Enum switcht (dessen Werte 0,1,2, ... sind) ist das Switch unschlagbar. Bei Strings ist das eben anders. Wenn man allerdings wenige Cases hat, baut der Compiler das Switch in ein If um. In meinen Fall waren das 6 Cases (default ist auch ein Case) aber ich weiß nicht ob das immer so ist.
switch (input)
{
case "Ä":
return "AE";
case "Ö":
return "OE";
case "Ü":
return "UE";
case "ß":
return "SS";
case "AE":
return "Ä";
case "OE":
return "Ö"; // bis hier ist es großes if, schneller als das unser eigenes Dictionary
case "UE": // ab hier ein Dictionary-Switch, langsamer als unser eigenes Dictionary, da wir ein Dict UND Switch benutzen.
return "Ü";
}
Unterm Strich:
Nimm ein static Dictionary. Das muss nur einmal initialisiert und befüllt werden. Das Switch-Mogel-Dictionary jedes mal. Viele Ifs gingen auch, sind aber hässlich. 🙂
Siehe auch:
http://weblogs.asp.net/justin_rogers/archive/2004/03/25/95806.aspx