standard sintaxis programar para net name guidelines framework documentacion codigos code classes c# syntax expression language-design parentheses

net - sintaxis para programar en c#



¿Por qué fue la declaración(j++); ¿prohibido? (3)

El siguiente código es incorrecto (verlo en ideone ):

public class Test { public static void Main() { int j = 5; (j++); // if we remove the "(" and ")" then this compiles fine. } }

error CS0201: solo las asignaciones, llamadas, incrementos, decrementos, esperas y nuevas expresiones de objetos se pueden usar como una declaración

  1. ¿Por qué se compila el código cuando eliminamos los paréntesis?
  2. ¿Por qué no se compila con los paréntesis?
  3. ¿Por qué se diseñó C # de esa manera?

Conocimientos profundos apreciados.

Haré lo mejor que pueda.

Como han señalado otras respuestas, lo que está sucediendo aquí es que el compilador está detectando que una expresión se está utilizando como una declaración . En muchos lenguajes, C, JavaScript y muchos otros, es perfectamente legal usar una expresión como una declaración. 2 + 2; es legal en estos idiomas, a pesar de que esta es una declaración que no tiene ningún efecto. Algunas expresiones son útiles solo por sus valores, algunas expresiones son útiles solo por sus efectos secundarios (como una llamada a un método de retorno nulo) y algunas expresiones, desafortunadamente, son útiles para ambos. (Como incremento)

El punto es: las declaraciones que consisten solo en expresiones son casi con certeza errores a menos que esas expresiones se consideren más útiles para sus efectos secundarios que sus valores . Los diseñadores de C # deseaban encontrar un punto medio, al permitir expresiones que generalmente se consideraban como efectos secundarios, mientras que no permitían aquellas que también se consideran útiles para sus valores. El conjunto de expresiones que identificaron en C # 1.0 fueron incrementos, decrementos, llamadas a métodos, asignaciones y, de forma algo controvertida, invocaciones de constructores.

A UN LADO: Uno normalmente piensa que la construcción de un objeto se usa por el valor que produce, no por el efecto secundario de la construcción; en mi opinión permitiendo new Foo(); es un poco una mala característica. En particular, he visto este patrón en el código del mundo real que causó un defecto de seguridad:

catch(FooException ex) { new BarException(ex); }

Puede ser sorprendentemente difícil detectar este defecto si el código es complicado.

Por lo tanto, el compilador funciona para detectar todas las declaraciones que consisten en expresiones que no están en esa lista. En particular, las expresiones entre paréntesis se identifican solo como eso: expresiones entre paréntesis. No están en la lista de "expresiones permitidas como declaraciones", por lo que no están permitidas.

Todo esto está al servicio de un principio de diseño del lenguaje C #. Si escribiste (x++); Probablemente estabas haciendo algo mal . Este es probablemente un error tipográfico para M(x++); o alguna cosa justa. Recuerde, la actitud del equipo compilador de C # no es " ¿podemos encontrar alguna forma de hacer que esto funcione? " La actitud del equipo compilador de C # es " si el código plausible parece un posible error, informemos al desarrollador ". A los desarrolladores de C # les gusta esa actitud.

Ahora, dicho todo esto, en realidad hay algunos casos extraños en los que la especificación de C # implica o establece directamente que los paréntesis no están permitidos, pero el compilador de C # los permite de todos modos. En casi todos esos casos, la discrepancia menor entre el comportamiento especificado y el comportamiento permitido es completamente inofensiva, por lo que los escritores del compilador nunca han solucionado estos pequeños errores. Puedes leer sobre eso aquí:

¿Hay alguna diferencia entre return myVar y return (myVar)?


En la especificación del lenguaje C #

Las declaraciones de expresión se utilizan para evaluar expresiones. Las expresiones que pueden usarse como declaraciones incluyen invocaciones de métodos, asignaciones de objetos usando el nuevo operador, asignaciones usando = y los operadores de asignación compuesta, operaciones de incremento y decremento usando los operadores ++ y - y esperan expresiones.

Poner paréntesis alrededor de una declaración crea una nueva llamada expresión entre paréntesis. De la especificación:

Una expresión entre paréntesis consiste en una expresión encerrada entre paréntesis. ... Una expresión entre paréntesis se evalúa evaluando la expresión entre paréntesis. Si la expresión entre paréntesis denota un espacio de nombres o tipo, se produce un error en tiempo de compilación. De lo contrario, el resultado de la expresión entre paréntesis es el resultado de la evaluación de la expresión contenida.

Dado que las expresiones entre paréntesis no se enumeran como una declaración de expresión válida, no es una declaración válida de acuerdo con la especificación. Nadie sabe con certeza por qué los diseñadores decidieron hacerlo de esta manera, pero mi apuesta es porque los paréntesis no son útiles si la declaración completa está entre paréntesis: stmt y (stmt) son exactamente iguales.


porque los corchetes alrededor del i++ están creando / definiendo una expresión ... como dice el mensaje de error ... no se puede usar una expresión simple como una declaración.

¿Por qué el lenguaje fue diseñado para ser así? para evitar errores, que tienen expresiones engañosas como declaraciones, que no producen efectos secundarios como tener el código

int j = 5; j+1;

la segunda línea no tiene efecto (pero puede que no lo hayas notado). Pero en lugar de que el compilador lo elimine (porque el código no es necesario). Explícitamente le pide que lo elimine (para que sepa el error) O lo arregle en caso de que haya olvidado escribir algo.

editar :

para aclarar más la parte sobre frenado ... los corchetes en c # (además de otros usos, como la conversión y la llamada a función), se usan para agrupar expresiones y devolver una sola expresión (marca de las subexpresiones).

en ese nivel de código solo se permiten declaraciones ...

j++; is a valid statement because it produces side effects

pero al usar el freno lo estás convirtiendo en una expresión

myTempExpression = (j++)

y esto

myTempExpression;

no es válido porque el compilador no puede asegurar que la expresión sea un efecto secundario (no sin incurrir en el problema de detención).