2009-04-08 11 views
25

Ich habe entdeckt, dass der folgende Code:Warum erstellt der C# -Compiler aus diesem Code eine PrivateImplementationDetails?

public static class MimeHelper 
    { 
     public static string GetMimeType(string strFileName) 
     { 
      string retval; 
      switch (System.IO.Path.GetExtension(strFileName).ToLower()) 
      { 
       case ".3dm": retval = "x-world/x-3dmf"; break; 
       case ".3dmf": retval = "x-world/x-3dmf"; break; 
       case ".a": retval = "application/octet-stream"; break; 
       // etc... 
       default: retval = "application/octet-stream"; break; 
      } 
      return retval; 
     } 
    } 

den Compiler verursacht dieses namespaceless, interne Klasse (kopiert von Reflector) zu erstellen:

<PrivateImplementationDetails>{621DEE27-4B15-4773-9203-D6658527CF2B} 
    - $$method0x60000b0-1 : Dictionary<String, Int32> 
    - Used By: MimeHelper.GetMimeType(String) : String 

Warum ist das so? Wie würde ich den obigen Code ändern, damit es (aus Interesse nur)

Dank

Andrew

+1

als Off-Thema, warum verwenden Sie zusätzliche Zeichenfolge Variable Retval, wenn Sie sofort vom Switch zurückkehren können? – abatishchev

+0

weil es ein Copy-and-Paste-Job von irgendwo war, ja konnte ich es ändern (und werde es ändern) –

Antwort

22

Es ist die Schaffung des Wörterbuchs zu handhaben, die Lookups der verschiedenen Fälle in der switch-Anweisung nicht geschieht anstatt mehrere ifs zu verzweigen, um den Rückgabewert zu setzen. Vertrauen Sie mir - Sie möchten nicht ändern, wie es funktioniert - es sei denn, Sie möchten die Karte explizit machen.

ASIDE: Ich hatte ursprünglich angenommen, dass das Wörterbuch eine Zuordnung von jedem Fall zu einem Index in eine andere Karte für die Rückgabewerte gespeichert. Laut @Scott (siehe Kommentare) speichert es tatsächlich einen Index für den Code, der für diesen Fall ausgeführt werden soll. Dies ist absolut sinnvoll, wenn man bedenkt, dass der Code, der für jeden Fall ausgeführt wird, unterschiedlich sein könnte und viel länger als in dem gegebenen Beispiel sein kann. EDIT: Basierend auf Ihrem Kommentar, ich denke, ich könnte versucht sein, die Mappings in einer externen Konfigurationsdatei zu speichern, sie beim Start einlesen, und erstellen Sie die tatsächliche Karte - entweder eine einzige Ebene Karte von Schlüssel Wert oder eine ähnliche mehrstufige Zuordnung von Schlüssel zu Index und von Index zu Wert. Ich denke, es wäre einfacher, diese Zuordnungen in einer Konfigurationsdatei zu verwalten, als den Code jedes Mal zu aktualisieren, wenn Sie einen bestimmten Fall hinzufügen oder entfernen müssen.

+0

Das dachte ich auch, aber als ich den Typ lokal kompiliert habe (sowohl Debug als auch Release) habe ich keinen Compiler gesehen generierte Sachen. –

+0

Andere Version des Compilers? Anderer Kontext? – tvanfosson

+0

Oder vielleicht haben Sie nicht so viel in den Code eingefügt, der durch die Ellipse ersetzt wurde, und es hat nicht die Notwendigkeit zur Optimierung ausgelöst? – tvanfosson

3

Siehe beispielsweise this.

4

Was passiert ist Compiler erstellt eine interne Klasse, die es zur Kompilierzeit ausgibt. Diese Klasse heißt <PrivateImplementationDetails>{99999999-9999-9999-9999-999999999999}, die GUID-Komponente dieser Klasse wird zur Kompilierzeit generiert und ändert sich daher mit jedem Build. Intern in dieser Klasse gibt es ein Dictionary, das die verschiedenen Case-Variablen enthält, und ein Int, das jedem Wert entspricht. Es ersetzt dann die switch-Anweisung mit einem Lookup im Dictionary, um das entsprechende int zu erhalten, und schaltet den int-Wert um (viel effizienter als eine Menge von Sting-Vergleichen).

Verwandte Themen