variable usa tipo que programacion pero locales las inicializar implícito float ejemplo definicion deben con como c# scope

c# - usa - que es double en programacion java



Alcance de variables de C#: ''x'' no se puede declarar en este ámbito porque daría un significado diferente a ''x'' (3)

¿No es esto simplemente erróneo?

No, esto no está mal en absoluto. Esta es una implementación correcta de la sección 7.5.2.1 de la especificación de C #, "Nombres simples, significados invariables en bloques".

La especificación declara:

Para cada aparición de un identificador dado como un nombre simple en una expresión o declarador, dentro del espacio de declaración de variable local de esa ocurrencia, cada otra aparición del mismo identificador como un nombre simple en una expresión o declarador debe referirse a la misma entidad. Esta regla garantiza que el significado de un nombre sea siempre el mismo dentro de un bloque, bloque de conmutación, instrucción for-, foreach- o using, o función anónima.

¿Por qué C # no puede diferenciar entre los dos ámbitos?

La pregunta no tiene sentido obviamente, el compilador puede diferenciar entre los dos ámbitos. Si el compilador no pudo diferenciar entre los dos ámbitos, ¿cómo podría producirse el error ? El mensaje de error dice que hay dos ámbitos diferentes y, por lo tanto, los ámbitos se han diferenciado.

¿El primer alcance IF no debe estar completamente separado del resto del método?

No, no debería. El alcance (y el espacio de declaración de variable local) definido por la instrucción de bloque en la consecuencia de la instrucción condicional es léxicamente una parte del bloque externo que define el cuerpo del método. Por lo tanto, las reglas sobre el contenido del bloque externo se aplican a los contenidos del bloque interno.

No puedo llamar a var desde fuera del if, por lo que el mensaje de error es incorrecto, porque la primera var no tiene relevancia en el segundo ámbito.

Esto es completamente incorrecto Es engañoso concluir que solo porque la variable local ya no está en el alcance, que el bloque externo no contiene un error. El mensaje de error es correcto

El error aquí no tiene nada que ver con si el alcance de cualquier variable se superpone al alcance de cualquier otra variable; lo único relevante aquí es que tiene un bloque, el bloque externo, en el que se usa el mismo nombre simple para referirse a dos cosas completamente diferentes. C # requiere que un nombre simple tenga un significado en todo el bloque que primero lo use .

Por ejemplo:

class C { int x; void M() { int x = 123; } }

Eso es perfectamente legal; el alcance de la x externa se superpone al alcance de la x interna, pero eso no es un error. Qué es un error es:

class C { int x; void M() { Console.WriteLine(x); if (whatever) { int x = 123; } } }

porque ahora el simple nombre "x" significa dos cosas diferentes dentro del cuerpo de M - significa "this.x" y la variable local "x". Es confuso para desarrolladores y mantenedores de código cuando el mismo nombre simple significa dos cosas completamente diferentes en el mismo bloque , por lo que es ilegal.

Permitimos que los bloques paralelos contengan el mismo nombre simple utilizado de dos maneras diferentes; esto es legal:

class C { int x; void M() { if (whatever) { Console.WriteLine(x); } if (somethingelse) { int x = 123; } } }

porque ahora el único bloque que contiene dos usos inconsistentes de x es el bloque externo, y ese bloque no contiene directamente ningún uso de "x", solo indirectamente .

if(true) { string var = "VAR"; } string var = "New VAR!";

Esto dará como resultado:

Error 1 Una variable local llamada ''var'' no se puede declarar en este ámbito porque daría un significado diferente a ''var'', que ya se usa en un alcance ''secundario'' para denotar algo más.

No hay nada que rompa la tierra realmente, pero ¿no es esto simplemente erróneo? Un compañero desarrollador y yo nos preguntábamos si la primera declaración debería tener un alcance diferente, por lo que la segunda declaración no puede interferir con la primera declaración.

¿Por qué C # no puede diferenciar entre los dos ámbitos? ¿El primer alcance IF no debe estar completamente separado del resto del método?

No puedo llamar a var desde fuera del if, por lo que el mensaje de error es incorrecto, porque la primera var no tiene relevancia en el segundo ámbito.


El problema aquí es en gran medida una buena práctica y prevención contra errores inadvertidos. Es cierto que el compilador C # podría diseñarse teóricamente de modo que no haya conflicto entre los ámbitos aquí. Sin embargo, esto sería mucho esfuerzo para obtener poca ganancia, según lo veo.

Considere que si la declaración de var en el ámbito primario estuviera antes de la instrucción if, habría un conflicto de nombres no resuelto. El compilador simplemente no diferencia entre los dos casos siguientes. El análisis se realiza únicamente en función del alcance y no del orden de la declaración / uso, como parece estar esperando.

El teóricamente aceptable (pero aún no válido en lo que se refiere a C #):

if(true) { string var = "VAR"; } string var = "New VAR!";

y lo inaceptable (ya que estaría ocultando la variable principal):

string var = "New VAR!"; if(true) { string var = "VAR"; }

ambos son tratados exactamente igual en términos de variables y ámbitos.

Ahora, ¿hay alguna razón real en este secenario por la que no se puede simplemente dar a una de las variables un nombre diferente? Supongo (espero) que sus variables reales no se llamen var , entonces realmente no veo que esto sea un problema. Si todavía intenta volver a utilizar el mismo nombre de variable, simplemente colóquelos en ámbitos hermanos:

if(true) { string var = "VAR"; } { string var = "New VAR!"; }

Sin embargo, esto, aunque es válido para el compilador, puede generar cierto grado de confusión al leer el código, por lo que recomiendo que no lo haga en casi todos los casos.


Esto es válido en C ++, pero una fuente de muchos errores y noches sin dormir. Creo que los chicos de C # decidieron que es mejor lanzar una advertencia / error, ya que es, en la gran mayoría de los casos, un error en lugar de algo que el codificador realmente quiere.

Here una discusión interesante sobre de qué partes de la especificación proviene este error.

EDITAR (algunos ejemplos) -----

En C ++, lo siguiente es válido (y realmente no importa si la declaración externa es anterior o posterior al alcance interno, será más interesante y propenso a errores si es anterior).

void foo(int a) { int count = 0; for(int i = 0; i < a; ++i) { int count *= i; } return count; }

Ahora imagine que la función tiene unas pocas líneas más y es posible que no sea fácil detectar el error. El compilador nunca se queja (no en los viejos tiempos, no está seguro de las versiones más nuevas de C ++), y la función siempre devuelve 0.

El comportamiento es claramente un error, por lo que sería bueno si un programa de c ++ - pelusa o el compilador señala esto. Si no es un error, es fácil solucionarlo simplemente cambiando el nombre de la variable interna.

Para colmo de males, recuerdo que GCC y VS6 tenían diferentes opiniones sobre dónde pertenecía la variable de contador en los bucles for. Uno dijo que pertenecía al alcance exterior y el otro dijo que no. Un poco molesto trabajar con código multiplataforma. Déjame darte otro ejemplo más para mantener mi línea cuenta.

for(int i = 0; i < 1000; ++i) { if(array[i] > 100) break; } printf("The first very large value in the array exists at %d/n", i);

Este código funcionaba en VS6 IIRC y no en GCC. De todos modos, C # ha limpiado algunas cosas, lo cual es bueno.