2012-05-23 7 views
5

Ho letto questa domanda (What is the scope of a lambda variable in C#?)Perché l'ambito variabile Lambda esiste all'esterno di LINQ Query?

Ma si tratta dello scope variabile di Lambda all'interno di LINQ Query.

Ora alla mia domanda

Diciamo che ho una semplice query LINQ.

var Foo = FoobBar.Select(x => x); 
var x = somefunction(); 

compilatore dice: A local variable 'x' cannot be declared in this scope because it would give a different meaning to 'x', which is already used in a 'child' scope to denote something else.

Perché è così? La variabile Lambda non dovrebbe cessare di esistere quando termina la query LINQ?

EDIT: Dopo le risposte di lettura sono arrivato a concludere che la sua parte esterna x (tornato dalla funzione) il cui ambito si estende all'interno LINQ Query.

+1

Dopo aver letto tutte le risposte sono giunto alla conclusione che è il contrario. l'ambito della variabile esterna esiste all'interno della query LINQ. –

+1

E viceversa ;-) Una lingua non sarebbe priva di refactoring-friendly se consentisse la compilazione del codice solo perché la variabile in conflitto ('var x = somefunction();') si trova sulla seconda riga, e quindi quando si sposta la seconda riga in prima linea, con grande dispiacere, non si compilerebbe più. C# esegue un meccanismo di pre-emptive, non consente a 'var x = someFunction()' di compilare anche se è in seconda linea, in quanto è possibile ridimensionare il codice in qualsiasi momento e metterlo in prima linea in seguito. Viviamo in un'epoca in cui un codice suscettibile di refactoring è la norma –

risposta

9

Non si tratta di LINQ si tratta di ambiti figlio.

Ad esempio:

foreach (var bar in FooBar.Bars) 
     { 
      var x = FooBar.GetFoo(); 
     } 
var x = new Foo(); 

produce esattamente lo stesso messaggio di errore del compilatore.

Per risolvere il problema è sufficiente posizionare le variabili in ambiti diversi (non annidati). Ad esempio:

foreach (var bar in FooBar.Bars) 
     { 
      var x = FooBar.GetBar(); 
     } 
{ 
    var x = new Foo(); 
} 
4

consente di guardare con attenzione,

var Foo = FoobBar.Select(x => x); 

vero l'ambito di x finisce nell'espressione

var x = somefunction() 

Ora questo è interessante, questo è ambito per l'intero metodo che detiene l'espressione Lamda troppo, quindi il compilatore non può distinguere poiché l'ambito di quest'ultimo si sovrappone al primo. e il messaggio molto istruttiva anche dare un significato diverso a 'x', che viene già utilizzato in ambito di un 'bambino'(Selezionare come nel tuo caso)

Similar scope question

forse si può includere le parentesi intorno l'altro in modo che sia portata è definita

{ 
var x = somefunction() 
} 
+0

Nell'ultimo snippet, significa che l'ambito di x è limitato all'interno di quelle parentesi graffe? –

+0

@NikhilAgrawal sì – V4Vendetta

1

non è chiaro (al compilatore), che 'x' si intende con il secondo 'x' (dopo la =>).

Che cosa succede se è stato scritto da:

var Foo = FoobBar.Select(y => x); 
var x = somefunction(); 

allora che x nel lambda sarebbe in contrasto con il risultato 'someFunction'.

1

Non è possibile dichiarare due variabili con lo stesso nome nello stesso ambito.

"stessa portata" nel senso che entrambi sono entrambi all'interno dell'ambito corrente

void method() 
{ 
    int a; 
    int a; //wrong! 
} 

o uno è nella corrente e l'altro è in un ambito bambino.

void method() 
{ 
    int a; 
    for(;;) 
    { 
     int a; //wrong again! 
    } 
} 

Questo legato alla progettazione e vale per qualsiasi variabile, da int s ai riferimenti lambda.

2

che se C# permetterebbe di esistere queste due variabili sullo stesso livello di ambito, questo non sarà possibile:

static void test() { 

    Action<int> x = (z) => { 
     Console.WriteLine(z);    
    }; 


    int[] i = { 5,2,0,1,3,1,4 }; 

    var kyrie = i.Select (x => x); 

} 

Come diresti a C# che si voleva assegnare il delegato d'azione denominato x per Kyrie variabile; o viceversa, come diresti a C# che volevi usare la proiezione intera di per sé? Come C# lo risolverà?

E la risoluzione dell'oscilloscopio C# è molto coerente sia che la si dichiari prima dell'altra variabile o dopo le altre variabili, che siano uguali. per esempio. http://www.anicehumble.com/2012/05/java-said-c-said-scope-consistency.html

per disambiguare quelli scenario, C# non consente di compilare un programma che hanno i nomi delle variabili che esiste allo stesso livello

E 'tutto di esprimere il vostro intento al compilatore in un non ambigua modo. E C# ha fatto un buon lavoro al riguardo

+0

+1 per "Si tratta di esprimere il proprio intento al compilatore in modo non ambiguo". Completamente giusto. –