Parece extraño especialmente para los desarrolladores de C ++. En C ++, solíamos marcar un parámetro como const
para estar seguros de que su estado no cambiará en el método. También hay otras razones específicas de C ++, como pasar const ref
para pasar por ref y estar seguro de que el estado no cambiará. Pero, ¿por qué no podemos marcar como parámetros de método const en C #?
¿Por qué no puedo declarar mi método de la siguiente manera?
....
static void TestMethod1(const MyClass val)
{}
....
static void TestMethod2(const int val)
{}
....
c#
language-agnostic
language-design
Incógnito
fuente
fuente
Respuestas:
Además de las otras buenas respuestas, agregaré otra razón más por la que no poner la constidad de estilo C en C #. Tu dijiste:
Si const realmente hiciera eso, sería genial. Const no hace eso. ¡La constante es mentira!
Const no ofrece ninguna garantía de que realmente pueda usar. Suponga que tiene un método que toma una constante. Hay dos autores de código: la persona que escribe la persona que llama y la persona que escribe la persona que llama . El autor de la llamada ha hecho que el método tome una constante. ¿Qué pueden asumir los dos autores que es invariante con respecto al objeto?
Nada. La persona que llama es libre de deshacerse de la constante y mutar el objeto, por lo que la persona que llama no tiene garantía de que llamar a un método que toma una constante no lo mutará. Del mismo modo, el destinatario no puede asumir que el contenido del objeto no cambiará durante la acción del destinatario; el llamado podría llamar a algún método mutante en un alias no constante del objeto const, y ahora el llamado objeto const ha cambiado .
Const estilo C no ofrece garantía de que el objeto no cambiará y, por lo tanto, está roto. Ahora, C ya tiene un sistema de tipos débil en el que puede hacer una reinterpretación de un doble en un int si realmente lo desea, por lo que no debería sorprender que también tenga un sistema de tipos débil con respecto a const. Pero C # fue diseñado para tener un buen sistema de tipos, un sistema de tipos en el que cuando dices "esta variable contiene una cadena", la variable en realidad contiene una referencia a una cadena (o nulo). No queremos en absoluto poner un modificador "const" de estilo C en el sistema de tipos porque no queremos que el sistema de tipos sea una mentira . Queremos que el sistema de tipos sea sólido para que pueda razonar correctamente sobre su código.
Const en C es una guía ; básicamente significa "puedes confiar en que no intentaré mutar esta cosa". Eso no debería estar en el sistema de tipos ; lo que hay en el sistema de tipos debe ser un hecho sobre el objeto sobre el que pueda razonar, no una guía para su uso.
Ahora, no me malinterpretes; el hecho de que la constante en C esté profundamente rota no significa que todo el concepto sea inútil. Lo que me encantaría ver es una forma realmente correcta y útil de anotación "const" en C #, una anotación que tanto los humanos como los compiladores podrían usar para ayudarlos a comprender 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 un cuadro" 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 compilador pueda verificar. O dibuje una caja que diga "este método puro muta el estado interno del objeto pero no de ninguna manera que sea observable fuera de la caja". Un objeto de este tipo no podría ser multiproceso automático de forma segura, pero podría memorizarse automáticamente . Hay todo tipo de anotaciones interesantes que podríamos poner en el código que permitirían optimizaciones enriquecidas y una comprensión más profunda. Podemos hacerlo mucho mejor que la débil anotación constante de estilo C.
Sin embargo, enfatizo que esto es solo una especulación . No tenemos planes firmes para poner este tipo de característica en ninguna versión futura hipotética de C #, si es que existe una, que no hayamos anunciado de una forma u otra. Es algo que me encantaría ver, y algo que el próximo énfasis en la computación de múltiples núcleos podría requerir, pero nada de esto debe interpretarse de ninguna manera como una predicción o garantía de alguna característica en particular o dirección futura para C #.
Ahora, si lo que quieres es simplemente una anotación en la variable local que es un parámetro que dice "el valor de este parámetro no cambia en todo el método", entonces, claro, eso se haría fácilmente. Podríamos admitir locales y parámetros de "solo lectura" que se inicializarían una vez, y un error en tiempo de compilación para cambiar el método. La variable declarada por la instrucción "using" ya es local; podríamos agregar una anotación opcional a todos los locales y parámetros para que actúen como "usando" variables. Nunca ha sido una característica de muy alta prioridad, por lo que nunca se ha implementado.
fuente
0xDEADBEEF
. Pero ambos serían una programación muy mala , y cualquier compilador moderno los captaría temprano y conmovedoramente. En el futuro, cuando escriba respuestas, no confunda lo que es técnicamente posible mediante el uso de las puertas traseras de un lenguaje con lo que es factible en el código real del mundo real. Información sesgada como esta confunde a los lectores menos experimentados y degrada la calidad de la información en SO.Una de las razones por las que no hay una corrección constante 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 que CLR no tiene una noción de corrección constante son, por ejemplo:
La corrección de la constante es prácticamente una característica del lenguaje que solo está presente en C ++. Por lo tanto, se reduce prácticamente a la misma argumentación de por qué CLR no requiere excepciones marcadas (que es una característica exclusiva del lenguaje Java).
Además, no creo que pueda introducir una característica de sistema de tipo tan fundamental en un entorno administrado sin romper la compatibilidad con versiones anteriores. Así que no cuente con que la corrección constante entre en el mundo de C #.
fuente
ref
parámetro (especialmente, en el caso de métodos / propiedades de estructurathis
). Si un método indica específicamente que no escribirá en unref
parámetro, entonces el compilador debería permitir que se pasen valores de solo lectura. Por el contrario, si un método indica que va a escribirthis
, el compilador no debe permitir que dicho método sea invocado en valores de solo lectura.Creo que hay dos razones por las que C # no es constante.
La primera es la comprensión . Pocos programadores de C ++ entienden la corrección constante. El ejemplo simple de
const int arg
es lindo, pero también lo he vistochar * const * const arg
: un puntero constante a punteros constantes a caracteres no constantes. La corrección constante de los punteros a las funciones es un nivel completamente nuevo de ofuscación.La segunda es porque los argumentos de clase son referencias pasadas por valor. Esto significa que ya hay dos niveles de constancia con los que lidiar, sin una sintaxis obviamente clara . Un punto de tropiezo similar son las colecciones (y colecciones de colecciones, etc.).
La corrección de constantes es una parte importante del sistema de tipos de C ++. En teoría, podría agregarse a C # como algo que solo se verifica en tiempo de compilación (no es necesario agregarlo al CLR y no afectaría al BCL a menos que se incluyera la noción de métodos de miembros const) .
Sin embargo, creo que esto es poco probable: la segunda razón (sintaxis) sería bastante difícil de resolver, lo que haría que la primera razón (comprensión) fuera aún más problemática.
fuente
modopt
ymodreq
en el nivel de metadatos para almacenar esa información (como C + / CLI ya lo hace - verSystem.Runtime.CompilerServices.IsConst
); y esto también podría extenderse trivialmente a los métodos const.const
significa "constante en tiempo de compilació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 # esreadonly
, pero ese solo es aplicable a los campos. Aparte de eso, no existe una noción similar a C ++ de corrección constante en C #.El fundamento es difícil de decir con certeza, porque hay muchas razones potenciales, pero mi suposición sería el deseo de mantener el lenguaje simple en primer lugar, y las ventajas inciertas de implementar este segundo.
fuente
Esto es posible desde C # 7.2 (diciembre de 2017 con Visual Studio 2017 15.5).
¡Solo para estructuras y tipos básicos ! , no para miembros de clases.
Debe usar
in
para enviar el argumento como entrada por referencia. Ver:Ver: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-parameter-modifier
Por tu ejemplo:
fuente