2009-04-17 10 views
12

Ich habe in dem reading this article about closures gewesen, sagen sie:Was ist das Besondere an Verschlüssen?

  • „alle Sanitär-Automatik ist“
  • der Compiler „erzeugt eine Wrapper-Klasse“ Sie und „verlängert die Lebensdauer der Variablen“
  • “ lokale Variablen ohne Sorge“kann
  • .NET-Compiler für Sie kümmern sich um die Sanitär nimmt usw.

so machte ich ein Beispiel, basierend auf ihren Code und mir scheint es, als obwohl die Schließungen nur ähnlich wie die regulären benannten Methoden funktionieren, die sich auch "ohne Sorgen um die lokalen Variablen kümmern" und in denen "alle Rohrleitungen automatisch sind".

Oder welches Problem hat dieses "Wrapping von lokalen Variablen" gelöst, das Schließungen so besonders/interessant/nützlich macht?

using System; 
namespace TestingLambda2872 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Func<int, int> AddToIt = AddToItClosure(); 

      Console.WriteLine("the result is {0}", AddToIt(3)); //returns 30 
      Console.ReadLine(); 
     } 

     public static Func<int, int> AddToItClosure() 
     { 
      int a = 27; 
      Func<int, int> func = s => s + a; 
      return func; 
     } 
    } 
} 

Antwort

So ist die Antwort auf diese ist Jon Skeet's article on closures, die Marc wies darauf hin, zu lesen. Dieser Artikel zeigt nicht nur die Evolution, die zu Lambda-Ausdrücken in C# führt, sondern zeigt auch, wie Closures in Java behandelt werden, eine ausgezeichnete Lektüre für dieses Thema.

+0

Andere Sprachen (z. B. Javascript) unterstützen Schließungen. Fragen Sie nach dem Konzept oder der spezifischen Implementierung von C#? – strager

+1

Ich denke, dieses Beispiel ist zu einfach, um die Macht der Schließungen zu verstehen. –

+0

@strager: Ich meine das Konzept im Allgemeinen, ich versuche, mich um Delegierte, Schließungen, Karten, Lambdas, "Lambda-Ausdrücke", "Lambda-Bäume", anonyme Funktionen, Currying usw. und im Allgemeinen die neue Paradigmen funktionaler Programmierung, die über eine Sprache hinausgehen, haben ihre Wurzeln in Mathematik usw. (Ich hatte C# in den Titel geschrieben, weil Stackoverflow Ihnen jetzt sagt, dass Ihr Titel es "nicht gut genug ist, fügen Sie einzigartige Wörter hinzu ...") –

Antwort

20

Ihr Beispiel ist nicht klar, und zeigt nicht (IMO) typische Capture-Nutzung (die einzige Sache ist a gefangen, die immer 3 ist, also nicht sehr interessant).

Betrachten Sie dieses Lehrbuch Beispiel (ein Prädikat):

List<Person> people = ... 
string nameToFind = ... 
Person found = people.Find(person => person.Name == nameToFind); 

Jetzt versuchen es ohne Verschluss; Sie brauchen viel mehr Arbeit zu tun, auch wenn wir faul sind:

PersonFinder finder = new PersonFinder(); 
finder.nameToFind = ... 
Person found = people.Find(finder.IsMatch); 
... 
class PersonFinder { 
    public string nameToFind; // a public field to mirror the C# capture 
    public bool IsMatch(Person person) { 
     return person.Name == nameToFind; 
    } 
} 

Der Capture-Ansatz erstreckt sich ferner auf viele Variablen in verschiedenen Bereichen - eine viel von Komplexität, die verborgen ist.

Abgesehen von den Namen ist das obige eine Näherung dessen, was der C# -Compiler hinter den Kulissen tut. Beachten Sie, dass wir, wenn zusätzliche Bereiche beteiligt sind, die verschiedenen Erfassungsklassen verketten (d. H. Innere Bereiche haben einen Verweis auf die Erfassungsklasse von äußeren Bereichen). Ziemlich komplex.

Jon Skeet hat eine gute article on this here und mehr in his book.

+0

(zu der gelöschten Frage, ob es "statisch" gemacht werden soll): Nein - weil verschiedene Threads möglicherweise nach verschiedenen Namen gleichzeitig suchen oder die Ausführung des Delegaten verzögern möchten. –

+1

+1 für die C# in Depth Teil auf Closures –

+2

+1 für diesen Satz in der C# in Depth Closures Artikel: "Closures können Sie einige Verhalten kapseln, übergeben Sie es wie jedes andere Objekt, und immer noch Zugriff auf den Kontext in was sie zuerst erklärt wurden " –

0

Die Schließung ist eine Funktionalität des Compilers. Sie sehen es nicht, es macht nur den Code, den Sie schreiben, funktioniert.

Ohne es wird der Aufruf von AddToIt (3) fehlschlagen, da das zugrunde liegende Lamda die lokale Variable a = 27 im Bereich von AddToItClusure() verwendet. Diese Variable ist nicht vorhanden, wenn AddToIt aufgerufen wird.

Aber wegen der Closure, ein Mechanismus, der vom Compiler verwendet wird, funktioniert der Code und Sie müssen sich nicht darum kümmern.