2010-02-25 13 views
6

zurück in der Schule, schrieben wir einen Compiler, wo geschweiften Klammer das Standardverhalten der Ausführung alle Ausdrücke hatten, und den letzten Wert zurück ... so dass Sie so etwas wie schreiben können:C# Scoping-Betreiber

int foo = { printf("bar"); 1 }; 

Gibt es etwas Äquivalent in C#? Zum Beispiel, wenn ich eine Lambda-Funktion schreiben möchte, die einen Nebeneffekt hat.

Je weniger Punkt über die Lambda-Nebenwirkung sein (nur ein Beispiel), mehr, wenn diese Funktionalität in Lisp ... zum Beispiel ist, haben Sie progn

Antwort

7

Im Prinzip ist, ist die Antwort von Vlad richtig, und Sie müssen nicht über die Lambda-Funktion zu erklären, wie ein Delegierter im Voraus.

Außer, die Situation in C# ist nicht so einfach, da der Compiler nicht, ob der syntaktische Lambda-Ausdruck als Delegierter (zB Func<int>) oder einen Ausdrucksbaum (zB Expression<Func<int>>) und auch, es kann beliebig sein kompiliert werden entscheiden können, soll anderer kompatibler Delegattyp So müssen Sie den Delegaten erstellen:

int foo = new Func<int>(() => { 
    Console.WriteLine("bar"); return 1; })(); 

Sie den Code vereinfachen kann leicht durch ein Verfahren definiert, die einfach den Delegaten zurückgibt und dann den Aufruf der Methode - die C# Compiler schließen die Delegattyp automatisch:

static Func<R> Scope<R>(Func<R> f) { return f; } 

// Compiler automatically compiles lambda function 
// as delegate and infers the type arguments of 'Scope' 
int foo = Scope(() => { Console.WriteLine("bar"); return 1; })(); 

Ich stimme zu, dass dies ein hässlicher Trick ist, der nicht verwendet werden sollte :-), aber es ist eine interessante Tatsache, dass es getan werden kann!

7

Es gibt nichts, was man von mit Nebenwirkungen zu stoppen in ein Lambda-Ausdruck.

Func<int> expr =() => 
{ 
    Console.WriteLine("bar"); 
    return 1; 
}; 
int foo = expr(); 
5
int foo = (() => { printf("bar"); return 1; })(); 

Edit: Vielen Dank für die konstruktive Kritik, es sollte

int i = ((Func<int>)(() => { printf("bar"); return 1; }))(); 
+5

Dies ist die richtige Antwort - das heißt, ernsthaft in Betracht ziehen, dies nicht zu tun. –

+2

Sie möchten vielleicht prüfen, ob der Code vor der Abstimmung kompiliert wird. Das tut es nicht. -1. – Aaronaught

+0

Ja, ja, 'printf' existiert nicht in C#. Aber die Antwort ist nicht darüber. – Vlad

3

Wir haben darüber nachgedacht, sogar noch kürzere Syntaxen als ()=>{M();} für die Definition eines Lambda zu erstellen, aber es ist nicht gelungen, eine Syntax zu finden, die beide gut liest und nicht leicht mit Blöcken, Sammel-/Objektinitialisierern verwechselt werden kann. oder Array-Initialisierer. Sie sind jetzt mit der Lambda-Syntax beschäftigt.