2009-06-10 12 views
2

Warum gibt es Verschlüsse für anonyme Methoden? Warum übergeben Sie nicht einfach den Status in die Methode, ohne dass der Overhead einer neuen Klasse generiert wird, in die die Closure-Variablen kopiert werden? Ist das nicht nur ein Rückfall zu "alles global machen"?Verschlüsse für anonyme Methoden in C# 3.0

Jemand sprechen mich, ich fühle mich wie ich hier etwas fehlt bin ...

Antwort

8

Rein, Bequemlichkeit ... Sie wissen nicht, wie viel Zustand Sie gehen zu müssen, bei der Definition, zum Beispiel ein Predicate<T> - betrachten:

List<int> data = new List<int> {1,2,3,4,5,6,7,8,9,10}; 
int min = int.Parse(Console.ReadLine()), max = int.Parse(Console.ReadLine()); 
List<int> filtered = data.FindAll(i => i >= min && i <= max); 

hier haben wir bestanden zwei zusätzliche Bits Zustand in Predicate<T> (min und max) - aber wir können List<T>.FindAll(Predicate<T>) nicht darüber wissen, da dies ein Anrufer Detail ist.

Die Alternative besteht darin, die Klassen selbst zu schreiben, aber das ist schwer, auch wenn wir faul sind:

class Finder { 
    public int min, max; 
    public bool CheckItem(int i) { return i >= min && i <= max;} 
} 
... 
Finder finder = new Finder(); 
finder.min = int.Parse(Console.ReadLine()); 
finder.max = int.Parse(Console.ReadLine()); 
List<int> filtered = data.FindAll(finder.CheckItem); 

ich über Sie weiß es nicht, aber ich ziehe es die Version mit der Schließung ... besonders wenn man bedenkt, wie komplex es wird, wenn man mehrere kontextabhängige Ebenen hat. Ich möchte, dass der Compiler sich darum sorgt.

Überlegen Sie auch, wie oft Sie solche Konstrukte verwenden, vor allem für Dinge wie LINQ: Sie würde nicht haben wollen es andere Art und Weise zu tun ...

+0

Ausgezeichnet und gut argumentiert; Danke! –

3

Der Aufwand für die Erstellung wahrscheinlich eine neue Klasse geht es um nicht etwas zu befürchten. Es ist nur eine bequeme Möglichkeit für die CLR, gebundene Variablen (die von der Schließung erfasst werden) auf dem Heap verfügbar zu machen. Sie sind immer noch nur im Rahmen der Schließung zugänglich, also im herkömmlichen Sinne überhaupt nicht "global".

Ich glaube der Grund für ihre Existenz ist hauptsächlich Bequemlichkeit für den Programmierer. In der Tat ist es das, was mich betrifft. Sie könnten das Verhalten einer Closure ziemlich gut emulieren, bevor sie in C# existierten, aber Sie erhalten nichts von der Einfachheit und dem syntaktischen Zucker, die C# 3.0 bietet. Der ganze Punkt über Closures ist, dass Sie die Variablen im übergeordneten Bereich nicht an die Funktion übergeben müssen, da sie automatisch gebunden sind. Es ist viel einfacher und sauberer für den Programmierer zu arbeiten, wirklich, wenn Sie bedenken, dass die Alternative true globale Variablen ist.

-1

Da die CLR sich darum kümmert, besteht die einfachste Methode zum Übergeben des Status an die Methode darin, automatisch eine Klasse zu generieren, die diesen Zustand einkapselt.

+2

Die CLR hat nichts damit zu tun - es ist der Compiler ... –

+0

Ich meinte, die CLR kümmert sich in dem Sinne, dass, wenn der Compiler die Klasse generiert, die Tatsache, dass es eine Klasse kümmert sich um diese Variablen weitergegeben wurde, ich denke, ich war unklar. – eulerfx

0

Mindestens ein Gedanke ist, dass Schließungen in anderen Sprachen wie Javascript vorhanden sind. Also schlossen sie wahrscheinlich Schließungen ein, um mit den früheren Erfahrungen der Leute mit anonymen Methoden übereinzustimmen.

0

Weil du das nehmen schreiben:

var divsor = [...] 
for(int x = 0; x < 10000000; x++){ 
    source[x] = source[x]/divsor   
} 

Und leicht biegen sie in diesem

var divsor = [...] 
Parallel.For(int x = 0; x < 10000000; x++,()=> { 
    source[x] = source[x]/divsor   
}) 
0

Einige Methoden eine bestimmte Signatur erfordern. Zum Beispiel:

public void set_name_on_click(string name) 
{ 
    button.Click += (s,e) => { button.Text = name; }; 
} 

Ein vollständiger Verschluss löst dies sehr sauber. Sie wollen sich wirklich nicht mit der anonymen Methodensignatur anlegen.