Child Scope & CS0136

Il codice seguente non riesce a compilare dichiarando “Una variabile locale chiamata ‘st’ non può essere dichiarata in questo ambito perché darebbe un significato diverso a ‘st’, che è già usato in un ambito ‘figlio’ per indicare qualcos’altro ‘:

var l = new List(); l.Find(st => st.EndsWith("12")); string st = "why this fails?"; 

Capisco perché questo non funzionerà:

  string preParent = ""; { string preParent = "Should fail cause we change the meaning"; } 

Quando facciamo quanto segue otteniamo “CS0103: Il nome ‘postParent’ non esiste nel contesto corrente”:

  { string postParent=string.Empty; } postParent = "Should this work?"; 

Quello che non capisco è perché il compilatore è abbastanza intelligente da vedere che postParent non è all’interno dell’ambito, ma non mi consente di definire una nuova variabile che ha lo stesso nome di una variabile utilizzata all’interno di un ambito figlio (che è ovviamente fuori di scopo a questo punto).

Il compilatore sta implementando un ambito semplice rifiutando di farmi usare la variabile? Se è così, questo ha senso.

===========

Modificato:

Immagino che ciò che trovo interessante sia come si possa avere la stessa variabile all’interno di due ambiti figlio in un unico metodo, quindi questo è valido:

  { string thisWorks= string.Empty; } { string thisWorks= "Should this work?"; } 

Sono solo un po ‘curioso che tu possa avere due variabili con lo stesso nome purché siano allo stesso livello (se guardi l’ambito come un albero). Questo ha senso perché puoi avere variabili locali in due metodi della stessa class con lo stesso nome.

Sono solo sorpreso che il compilatore sia in grado di differenziare e consentire questo, mentre non permetterebbe la variabile postParent. E questa è una limitazione tecnica o è stata una decisione di progettazione? Questo è quello che cerco davvero di ottenere 😉

Sì, il compilatore sta applicando l’ambito. Si noti che l’ambito di una variabile è il blocco lessicale di cui fa parte – non solo dal punto di dichiarazione in poi, ma dall’intero ambito.

Il compilatore si lamenta perché l’assegnazione a postParent è al di fuori del suo ambito (che è solo le parentesi graffe nidificate). Se si è tentato di dichiarare una nuova variabile nel punto in cui si sta attualmente assegnando a postParent il problema sarebbe con il blocco nidificato, poiché l’ambito di postParent includerebbe quel blocco nidificato, anche se era prima della dichiarazione.

Gli ambiti sono descritti nella sezione 3.7 della specifica C # 3.0.

EDIT: per rispondere alla modifica della tua domanda.

Sono solo due semplici regole:

  • non è ansible dichiarare una variabile locale quando un’altra variabile locale con lo stesso nome è in ambito
  • l’ambito di una variabile locale è il blocco in cui si verifica la dichiarazione

Sono sicuro che il linguaggio avrebbe potuto essere progettato in modo tale che lo scope iniziasse solo al punto di dichiarazione, ma penso che sia più semplice (in termini di complessità del linguaggio) considerare gli ambiti come semplici blocchi – così tutte le variabili locali dichiarate nello stesso blocco avere lo stesso scopo, per esempio. Ciò rende la vita molto più semplice se si considerano anche le variabili catturate, poiché ciò che viene catturato dipende dall’ambito e gli ambiti nidificati rendono la vita interessante …

EDIT: la specifica della lingua ha questo da dire sull’esempio di espressione lambda originale – è la sezione 7.14.1:

La funzione opzionale anonimo-funzione di una funzione anonima definisce i nomi e facoltativamente i tipi dei parametri formali per la funzione anonima. Lo scopo dei parametri della funzione anonima è il corpo della funzione anonima. Insieme alla lista dei parametri (se fornita), il corpo del metodo anonimo costituisce uno spazio di dichiarazione. Per questo motivo, si tratta di un errore in fase di compilazione per il nome di un parametro della funzione anonima in modo che corrisponda al nome di una variabile locale, costante locale o parametro il cui ambito include l’espressione del metodo anonimo o espressione lambda.

Questo aiuta?

Stai dichiarando una variabile in un ambito limitato e cercando di usarla al di fuori di tale ambito. Il compilatore presuppone che non si desideri accedervi in ​​modo da poter dichiarare una variabile con lo stesso nome da qualche altra parte nel file. Il tuo tentativo di eseguire il vecchio trucco C di assumere la variabile vivrà immediatamente al di fuori dell’ambito. Ad esempio, questo ha funzionato in versioni precedenti di C / C ++, ma non funziona più.

 for (int i=0; i<10; i++) { cout < <”In the loop i is “<< i << endl; } cout << “outside of the loop i is “ << i << endl; //this only compiles with old C/C++ compilers.