Declaraciones de variables después de declaraciones if

Surgió un problema en otro foro y supe cómo solucionarlo, pero reveló una característica del comstackdor peculiar para mí. La persona obtenía el error “La statement incrustada no puede ser una statement o una statement etiquetada” porque tenían una statement de una variable que seguía una instrucción if sin corchetes. Esa no era su intención, pero habían comentado la línea de código que sigue inmediatamente a la statement if, que hacía que la statement de la variable fuera la línea de código de facto que debía ejecutarse. De todos modos, ese es el fondo, lo que me lleva a esto.

El siguiente código es ilegal

if (true) int i = 7; 

Sin embargo, si lo incluye entre corchetes, todo es legal.

 if (true) { int i = 7; } 

Ninguna pieza de código es útil. Sin embargo, el segundo está bien. ¿Cuál es específicamente la explicación de este comportamiento?

La especificación del lenguaje C # distingue entre tres tipos de declaraciones (ver el capítulo 8 para más detalles). En general, puede tener estas declaraciones:

  • statement-statement – mi suposición de que esto es para la antigua statement goto
  • statement-statement – que sería una statement de variable
  • embedded-statement – que incluye casi todas las declaraciones restantes

En la sentencia if , el cuerpo debe estar incrustado-statement , lo que explica por qué la primera versión del código no funciona. Aquí está la syntax de if de la especificación (sección 8.7.1):

if ( boolean-expression ) embedded-statement
if ( boolean-expression ) embedded-statement else embedded-statement

Una statement de variable es statement-statement , por lo que no puede aparecer en el cuerpo. Si encierra la statement entre paréntesis, obtendrá un bloque de instrucción, que es una statement incrustada (y por lo tanto puede aparecer en esa posición).

Cuando no incluye los corchetes, ejecuta la siguiente línea como si estuviera rodeada por corchetes. Dado que no tiene mucho sentido declarar una variable en esa línea (no podrá usarla nunca), el comstackdor de C # no permitirá que esto evite que lo haga accidentalmente sin saberlo (lo que podría introducir errores sutiles). )

Aquí hay una parte de Eric Lippert sobre el comstackdor de C # en esta respuesta SO sobre la resolución de nombres:

… C # no es un lenguaje de “adivina qué significaba el usuario” … el comstackdor, por diseño, se queja en voz alta si la mejor coincidencia es algo que no funciona

Todos los comstackdores le permitirán comstackr código que es inútil o de muy poco uso. Simplemente hay demasiadas formas en que un desarrollador puede usar el lenguaje para crear constructos sin uso. Hacer que el comstackdor los atrape a todos es simplemente demasiado esfuerzo y, por lo general, no vale la pena.

El segundo caso se menciona directamente en la especificación de lenguaje C # al comienzo de la sección 8.0

El ejemplo da como resultado un error en tiempo de comstackción porque una sentencia if requiere una instrucción incrustada en lugar de una instrucción para su twig if. Si se permitiera este código, entonces la variable i sería declarada, pero nunca podría ser utilizada. Sin embargo, tenga en cuenta que al colocar la statement de i en un bloque, el ejemplo es válido.

Código de ejemplo

 void F(bool b) { if (b) int i = 44; } 

Agregar los frenos de cierre y apertura en la parte else del if me ayudó como he hecho a continuación en comparación con lo que estaba haciendo antes de agregarlos;

Antes: esto causó el error:

 protected void btnAdd_Click(object sender, EventArgs e) { if (btnAdd.Text == "ADD") { CATEGORY cat = new CATEGORY { NAME = tbxCategory.Text.Trim(), TOTALSALEVALUE = tbxSaleValue.Text.Trim(), PROFIT = tbxProfit.Text.Trim() }; dm.AddCategory(cat, tbxCategory.Text.Trim()); } else // missing brackets - this was causing the error var c = getCategory(); c.NAME = tbxCategory.Text.Trim(); c.TOTALSALEVALUE = tbxSaleValue.Text.Trim(); c.PROFIT = tbxProfit.Text.Trim(); dm.UpdateCategory(c); btnSearchCat_Click(btnSearchCat, e); } 

Después: añadidos corchetes en la twig else

 protected void btnAdd_Click(object sender, EventArgs e) { if (btnAdd.Text == "ADD") { CATEGORY cat = new CATEGORY { NAME = tbxCategory.Text.Trim(), TOTALSALEVALUE = tbxSaleValue.Text.Trim(), PROFIT = tbxProfit.Text.Trim() }; dm.AddCategory(cat, tbxCategory.Text.Trim()); } else { var c = getCategory(); c.NAME = tbxCategory.Text.Trim(); c.TOTALSALEVALUE = tbxSaleValue.Text.Trim(); c.PROFIT = tbxProfit.Text.Trim(); dm.UpdateCategory(c); } btnSearchCat_Click(btnSearchCat, e); }