Ho un'immaginazione debole per quanto riguarda i nomi, quindi spesso mi ritrovo a riutilizzare gli identificatori nel mio codice. Questo mi ha fatto incontrare questo specifico problema.Parametro Lambda in conflitto con il campo classe sul campo di accesso in ambito successivo
Ecco qualche esempio di codice:
public delegate void TestDelegate(int test);
public class Test
{
private int test;
private void method(int aaa)
{
TestDelegate del = test => aaa++;
test++;
}
public static void Main()
{
}
}
Qui ci sono gli errori di compilazione (in uscita da ideone):
prog.cs(11,3): error CS0135: `test' conflicts with a declaration in a child block
prog.cs(9,22): (Location of the symbol related to previous error)
Compilation failed: 1 error(s), 0 warnings
Linea 11 contiene test++
, linea 9 contiene la lambda.
Per inciso, Visual Studio 2013 dà un errore diverso:
'test' conflicts with the declaration 'Namespace.Test.test'
L'errore si verifica presso l'incremento sulla linea 11 solo.
Il codice viene compilato correttamente se commento la riga 9 (la lambda) o la riga 11 (l'incremento).
Questo problema è una sorpresa per me - ero sicuro che i nomi dei parametri lambda possono entrare in conflitto solo con i nomi delle variabili di metodo locali (che è una sorta di conferma della compilazione del codice quando commento l'incremento). Inoltre, come può il parametro lambda influenzare l'incremento, che è proprio al di fuori dell'ambito del lambda?
Non riesco a capire come funziona ... Che cosa ho fatto di sbagliato? E cosa significano i messaggi di errore criptico in questo caso?
EDIT dopo tutte le grandi risposte:
Quindi penso ho finalmente capito la regola che mi sono rotto. Non è ben scritto nelle specifiche C# (7.6.2.1, vedere la risposta di Jon Skeet per la citazione). Ciò che è stato supposto significare è qualcosa di simile:
è possibile Non utilizzare lo stesso identificatore di fare riferimento a cose diverse (entità) nello stesso "spazio locale dichiarazione della variabile" se uno dei offendere usa è (direttamente) situato in un ambito che può essere "visto" dall'ambito in cui l'altro è (direttamente) situato.
Non lo standard del fraseggio standard, ma spero che tu abbia capito cosa intendo. Questa regola avrebbe dovuto permettere questo:
{
int a;
}
{
int a;
}
perché nessuno degli scopi delle due variabili a
possono essere "visti" dal campo di applicazione di altri;
e disattivare questo:
{
int a;
}
int a;
perché la seconda dichiarazione variabile è "visto" dalla portata della prima variabile
e disattivare questo:
class Test
{
int test;
void method()
{
{
int test;
}
test++;
}
}
causa l'incremento del campo può essere "visto" dall'ambito del blocco (non essendo una dichiarazione non importa).
Sembra che C# 6 abbia cambiato questa regola, in particolare rendendo legittimo l'ultimo esempio (e il mio codice originale), anche se non capisco esattamente come.
Per favore correggimi se ho fatto degli errori in questi esempi.
Questo codice viene compilato per me con Roslyn e con Mono 4.1.0.0 (costruito da capo alcune settimane fa). –
Ricevo lo stesso errore (l'ultimo) in VS2013 (.NET 4.5). –
@JonSkeet: whoa, quindi questo potrebbe essere un * bug * in csc? O_o (oddio, mi sento così bene adesso) – Mints97