c# - references - Child Scope y CS0136
using static c# (2)
El siguiente código no se puede compilar al indicar "No se puede declarar una variable local llamada ''st'' en este ámbito porque daría un significado diferente a ''st'', que ya se usa en un alcance ''secundario'' para denotar algo más":
var l = new List<string>();
l.Find(st => st.EndsWith("12"));
string st = "why this fails?";
Entiendo por qué esto no funcionará:
string preParent = "";
{
string preParent = "Should fail cause we change the meaning";
}
Cuando hacemos lo siguiente, obtenemos "CS0103: El nombre ''postParent'' no existe en el contexto actual":
{
string postParent=string.Empty;
}
postParent = "Should this work?";
Lo que no entiendo es por qué el compilador es lo suficientemente inteligente como para ver que postParent no está dentro del alcance, pero no me deja definir una nueva variable que tenga el mismo nombre que una variable utilizada en un ámbito hijo (que obviamente está fuera de alcance en este punto).
¿Es el compilador simple que impone el alcance negándose a permitirme usar la variable? Si es así, esto tiene sentido.
===========
Editado:
Creo que lo que también me parece interesante es cómo puedes tener la misma variable dentro de dos ámbitos secundarios en un único método, por lo que esto es válido:
{
string thisWorks= string.Empty;
}
{
string thisWorks= "Should this work?";
}
Estoy un poco curioso de que puedas tener dos variables con el mismo nombre, siempre y cuando estén en el mismo nivel (si miras el alcance como un árbol). Esto tiene sentido porque puede tener variables locales en dos métodos de la misma clase con el mismo nombre.
Me sorprende que el compilador pueda diferenciar y permitir esto, mientras que no permitiría la variable postParent. ¿Y esto es una limitación técnica o fue esta una decisión de diseño? Eso es a lo que realmente intento llegar ;-)
Sí, el compilador está aplicando el alcance. Tenga en cuenta que el alcance de una variable es el bloque léxico del que forma parte, no solo desde el punto de declaración en adelante, sino desde el alcance completo.
El compilador se queja porque la asignación a postParent
está fuera de su alcance (que son solo las llaves anidadas). Si intentas declarar una nueva variable en el punto en el que estás asignando actualmente a postParent
el problema sería con el bloque anidado, ya que el alcance de postParent
incluiría ese bloque anidado, aunque fuera antes de la declaración.
Los ámbitos se describen en la sección 3.7 de la especificación C # 3.0.
EDITAR: Para responder a su pregunta, edite.
Son solo dos reglas simples:
- no puede declarar una variable local cuando otra variable local con el mismo nombre está en el alcance
- el alcance de una variable local es el bloque en el que se produce la declaración
Estoy seguro de que el lenguaje podría haber sido diseñado de tal manera que el alcance solo comenzó en el momento de la declaración, pero creo que es más simple (en términos de complejidad del lenguaje) considerar los ámbitos como solo bloques, por lo que todas las variables locales declaradas en el mismo bloque tienen el mismo alcance, por ejemplo. Eso simplifica mucho la vida al considerar las variables capturadas, ya que lo que se captura depende del alcance, y los ámbitos anidados hacen que la vida sea interesante ...
EDITAR: La especificación de idioma tiene esto que decir sobre el ejemplo de expresión lambda original - es la sección 7.14.1:
La función anónima-firma opcional de una función anónima define los nombres y opcionalmente los tipos de los parámetros formales para la función anónima. El alcance de los parámetros de la función anónima es anonymous-function-body. Junto con la lista de parámetros (si se proporciona), el cuerpo de método anónimo constituye un espacio de declaración. Por esta razón, es un error en tiempo de compilación para el nombre de un parámetro de la función anónima que coincida con el nombre de una variable local, una constante local o un parámetro cuyo alcance incluye la expresión-método-anónima o la expresión-lambda.
¿Eso ayuda?
Está declarando una variable en un alcance limitado e intentando usarla fuera de ese alcance. El compilador supone que no desea tener acceso a él, por lo que puede declarar una variable con el mismo nombre en otro lugar del archivo. Estás tratando de hacer el viejo truco C de suponer que la variable vivirá inmediatamente fuera del alcance. Por ejemplo, esto solía funcionar en versiones anteriores de C / C ++ pero ya no funciona.
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.