2010-02-25 15 views
6

tornati a scuola, abbiamo scritto un compilatore in cui le parentesi graffe hanno avuto il comportamento predefinito di eseguire tutte le espressioni, e restituendo l'ultimo valore ... così si potrebbe scrivere qualcosa di simile:C# scoping operatore

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

C'è qualcosa di equivalente in C#? Per esempio, se voglio scrivere una funzione lambda che ha un effetto collaterale.

Il punto in meno essendo circa l'effetto collaterale lambda (solo un esempio), di più se v'è questa funzionalità ... per esempio in Lisp, avete progn

risposta

7

In linea di principio, la risposta da Vlad è corretta e non è necessario dichiarare la funzione lambda come un delegato in anticipo.

eccezione, la situazione non è così semplice in C#, perché il compilatore non può decidere se l'espressione lambda sintattica deve essere compilato come un delegato (ad es Func<int>) o un albero di espressione (ad esempio Expression<Func<int>>) ed inoltre, può essere qualsiasi altro tipo di delegato compatibile. Quindi, è necessario creare il delegato:

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

È possibile semplificare il codice un po 'attraverso la definizione di un metodo che restituisce semplicemente il delegato e quindi chiamando il metodo - il C# compilatore dedurre il tipo delegato automaticamente:

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; })(); 

Sono d'accordo che questo è un brutto trucco che non dovrebbe essere usato :-), ma è un fatto interessante che possa essere fatto!

7

Non c'è nulla ti impedisce di avere effetti collaterali a un'espressione lambda.

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

Edit: Grazie per la critica costruttiva, che dovrebbe essere

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

Questa è la risposta giusta - questo ha detto, seriamente, considera di non farlo. –

+2

Si potrebbe voler verificare effettivamente se il codice viene compilato prima di votare. Questo no. -1. – Aaronaught

+0

Sì, sì, 'printf' non esiste in C#. Ma la risposta non è su questo. – Vlad

3

Abbiamo preso in considerazione l'elaborazione di sintassi ancora più brevi di ()=>{M();} per la definizione di un lambda, ma non siamo riusciti a trovare una sintassi che sia correttamente leggibile e che non sia facilmente confusa con i blocchi, inizializzatori di raccolta/oggetto, o inizializzatori di array. Sei bloccato con la sintassi lambda per ora.