¿Por qué los parámetros de const no están permitidos en C #?

Parece extraño especialmente para los desarrolladores de C ++. En C ++ solíamos marcar un parámetro como const para asegurarnos de que su estado no cambiará en el método. También existen otros motivos específicos de C ++, como pasar const ref para pasar por ref y asegurarse de que no se cambie el estado. Pero ¿por qué no podemos marcar como parámetros del método const en C #?

¿Por qué no puedo declarar mi método como el siguiente?

  .... static void TestMethod1(const MyClass val) {} .... static void TestMethod2(const int val) {} .... 

Además de las otras buenas respuestas, agregaré otra razón más para no poner la constness del estilo C en C #. Tu dijiste:

marcamos parámetro como const para asegurarnos de que su estado no cambiará en el método.

Si const realmente hiciera eso, sería genial. Const no hace eso. ¡La const es una mentira!

Const no ofrece ninguna garantía de que pueda usar realmente. Supongamos que tiene un método que requiere algo. Hay dos autores de código: la persona que escribe la persona que llama y la persona que escribe el destinatario . El autor del llamado ha hecho que el método tome una const. ¿Qué pueden suponer los dos autores es invariable sobre el objeto?

Nada. El destinatario es libre de descartar el const y mutar el objeto, por lo que la persona que llama no tiene ninguna garantía de que llamar a un método que tome una const en realidad no lo mute. De manera similar, el destinatario no puede suponer que el contenido del objeto no cambiará a lo largo de la acción del destinatario; el llamado podría llamar a algún método de mutación en un alias no const del objeto const, y ahora el llamado objeto const ha cambiado .

C-style const no proporciona ninguna garantía de que el objeto no cambie y, por lo tanto, se rompa. Ahora, C ya tiene un sistema de tipo débil en el que puedes hacer una reinterpretación de un doble en un int si realmente quieres, por lo que no debería sorprender que tenga un sistema de tipo débil con respecto a const también. Pero C # fue diseñado para tener un buen sistema de tipo, un sistema de tipo donde cuando diga “esta variable contiene una cadena” la variable realmente contiene una referencia a una cadena (o nulo). Absolutamente no queremos poner un modificador de “const” de estilo C en el sistema de tipos porque no queremos que el sistema de tipo sea una mentira . Queremos que el sistema de tipos sea fuerte para que pueda razonar correctamente sobre su código.

Const en C es una guía ; básicamente significa “puedes confiar en mí para no intentar mutar esta cosa”. Eso no debería estar en el sistema de tipos ; las cosas en el sistema de tipo deben ser un hecho sobre el objeto que puede razonar, no una pauta para su uso.

Ahora, no me malinterpretes; El hecho de que const en C esté profundamente roto no significa que todo el concepto sea inútil. Lo que me gustaría ver es una forma realmente correcta y útil de la anotación “const” en C #, una anotación que los humanos y los comstackdores podrían usar para ayudarlos a entender el código, y que el tiempo de ejecución podría usar para hacer cosas como la paralelización automática y otras optimizaciones avanzadas.

Por ejemplo, imagina si pudieras “dibujar una caja” alrededor de un trozo de código y decir “Te garantizo que este trozo de código no realiza mutaciones en ningún campo de esta clase” de una manera que el comstackdor pueda verificar. O dibuja una caja que diga “este método puro muta el estado interno del objeto pero no de ninguna manera que se pueda observar fuera de la caja”. Tal objeto no se puede subprocesar con seguridad de forma automática, pero podría ser memorizado automáticamente . Hay todo tipo de anotaciones interesantes que podríamos poner en el código que permitiría optimizaciones ricas y una comprensión más profunda. Podemos hacer mucho mejor que la anotación débil const de estilo C.

Sin embargo, enfatizo que esto es solo especulación . No tenemos planes firmes de incluir este tipo de características en ninguna versión futura hipotética de C #, si es que hay una, que no hemos anunciado de una forma u otra. Es algo que me encantaría ver, y algo que podría requerir el próximo énfasis en la computación multinúcleo, pero nada de esto debe interpretarse de ninguna manera como una predicción o garantía de ninguna característica particular o dirección futura para C #.

Ahora, si lo que quieres es simplemente una anotación sobre la variable local que es un parámetro que dice “el valor de este parámetro no cambia a lo largo del método”, entonces, claro, eso sería fácil de hacer. Podríamos admitir locales y parámetros de “solo lectura” que se inicializarían una vez, y un error en tiempo de comstackción para cambiar en el método. La variable declarada por la statement “using” ya es local; podríamos agregar una anotación opcional a todos los locales y parámetros para hacerlos actuar como “usar” variables. Nunca ha sido una función de prioridad muy alta, por lo que nunca se ha implementado.

Una de las razones por las que no hay const correctness en C # es porque no existe en el nivel de tiempo de ejecución. Recuerde que C # 1.0 no tenía ninguna característica a menos que fuera parte del tiempo de ejecución.

Y varias razones por las cuales el CLR no tiene una noción de const correctness son, por ejemplo:

  1. Esto complica el tiempo de ejecución; además, la JVM tampoco la tenía, y la CLR básicamente comenzó como un proyecto para crear un tiempo de ejecución similar a JVM, no un tiempo de ejecución similar a C ++.
  2. Si hay const correctness en el nivel de tiempo de ejecución, debe haber const correctness en el BCL, de lo contrario la característica es bastante inútil en lo que se refiere a .NET Framework.
  3. Pero si el BCL requiere corrección const, cada idioma en la parte superior de la CLR debe ser compatible con la corrección de const (VB, JavaScript, Python, Ruby, F #, etc.) Eso no va a suceder.

La corrección de Const es prácticamente una característica del lenguaje solo presente en C ++. Así que básicamente se reduce a la misma argumentación sobre por qué el CLR no requiere excepciones comprobadas (que es una característica de solo lenguaje de Java).

Además, no creo que pueda introducir una característica de sistema de tipo fundamental en un entorno administrado sin romper la compatibilidad con versiones anteriores. Por lo tanto, no confíe en la exactitud de const alguna vez ingresando al mundo de C #.

Creo que hay dos razones por las que C # no es correcto.

El primero es la comprensión . Pocos progtwigdores de C ++ entienden const-correctness. El ejemplo simple de const int arg es lindo, pero también he visto char * const * const arg – un puntero constante para apuntadores constantes a caracteres no constantes. Const-corrección en punteros a funciones es un nuevo nivel de ofuscación.

El segundo es porque los argumentos de clase son referencias pasadas por valor. Esto significa que ya hay dos niveles de constness para tratar, sin una syntax obviamente clara. Un punto de tropiezo similar son las colecciones (y colecciones de colecciones, etc.).

Const-correctness es una parte importante del sistema de tipo C ++. Podría, en teoría, agregarse a C # como algo que solo se verifica en tiempo de comstackción (no es necesario agregarlo al CLR, y no afectaría el BCL a menos que se incluyera la noción de métodos de miembros de la const) .

Sin embargo, creo que esto es poco probable: la segunda razón (syntax) sería bastante difícil de resolver, lo que haría que la primera razón (la comprensión) sea aún más un problema.

const significa “constante de tiempo de comstackción” en C #, no “de solo lectura pero posiblemente mutable por otro código” como en C ++. Un análogo aproximado de C ++ const en C # es de readonly , pero ese solo es aplicable a los campos. Aparte de eso, no existe una noción de const de C ++ en absoluto en C #.

El fundamento es difícil de decir con certeza, porque hay muchas razones posibles, pero creo que sería el deseo de mantener el lenguaje simple en primer lugar, y las inciertas ventajas de implementar este segundo.