2009-01-15 6 views
6

Dies wurde in meiner anderen Frage erwähnt und ich dachte, es könnte nützlich sein, es dem Datensatz hinzuzufügen. Im folgenden Programm, das, falls vorhanden, der lokal definierten Delegaten zwischen den Aufrufen der Work-Methode zwischengespeichert wird, anstatt jedes Mal neu erstellt zu werden?Welche (falls vorhanden) lokal definierten Delegaten werden zwischen Methodenaufrufen zwischengespeichert?

namespace Example 
{ 
    class Dummy 
    { 
     public int age; 
    } 

    class Program 
    { 
     private int field = 10; 

     static void Main(string[] args) 
     { 
      var p = new Program(); 

      while (true) 
      { 
       p.Work(); 
      } 
     } 

     void Work() 
     { 
      int local = 20; 

      Action a1 =() => Console.WriteLine(field); 
      Action a2 =() => Console.WriteLine(local); 
      Action a3 =() => Console.WriteLine(this.ToString()); 
      Action a4 =() => Console.WriteLine(default(int)); 
      Func<Dummy, Dummy, bool> dummyAgeMatch = (l, r) => l.age == r.age; 

      a1.Invoke(); 
      a2.Invoke(); 
      a3.Invoke(); 
      a4.Invoke(); 
      dummyAgeMatch.Invoke(new Dummy() { age = 1 }, new Dummy(){ age = 2 }); 
     } 
    } 
} 

Antwort

7

auf das, was Reflector zeigt, ist die letzten zwei (a4 und dummyAgeMatch) von der # 3.0-Compiler MS C (in Feldern als "CS $ <> 9_CachedAnonymousMethodDelegate5" und "CS < $> 9_CachedAnonymousMethodDelegate6" zwischengespeichert werden, in mein besonderer Build).

Diese können zwischengespeichert werden, während offensichtlich die anderen von erfassten Variablen abhängen.

Ich glaube nicht, dass das Verhalten von der Spezifikation vorgeschrieben ist, aber der Mono-Compiler verhält sich auf die gleiche Weise (mit verschiedenen Variablennamen).

5

Nun, um die spezifische Frage zu beantworten: die letzten beiden sind die einzigen, die zwischengespeichert werden, da sie nichts erfassen. Sie können dies im Reflektor sehen (aber es ist nicht schön). Natürlich können Sie sie optimieren zu sie, indem man in args wiederverwendbar machen:

Action<Program> a1 = p => Console.WriteLine(p.field); 
Action<int> a2 = i => Console.WriteLine(i); 
Action<Program> a3 = p => Console.WriteLine(p.ToString()); 
Action a4 =() => Console.WriteLine(default(int)); 
Func<Dummy, Dummy, bool> dummyAgeMatch = (l, r) => l.age == r.age; 

Und this in a1/a3 und local in a2 passieren. Weil keiner von ihnen irgendwas mehr direkt erfasst, können alle im Cache zwischengespeichert werden (CS$<>9__CachedAnonymousMethodDelegate5 bis CS$<>9__CachedAnonymousMethodDelegate9 für mich zumindest). Natürlich verlieren sie dann die Fähigkeit, die (zuvor erfasste) Variable direkt neu zuzuweisen, aber FP-Befürworter werden das sowieso nicht mögen; -p Sie können den aktualisierten Wert immer als Rückgabewert übergeben oder einen Delegattyp deklarieren mit ref Argumente (Ich empfehle es jedoch nicht).

+0

Danke - das ist Roman! – xyz

Verwandte Themen