// x es una variable normal, no una constante int x = 123; // Error: x no tiene porqué tener valor constante (aunque aquí lo tenga) const int y = x +123;
|
Debido a la necesidad de que el valor dado a una constante sea precisamente constante, no tiene mucho sentido crear constantes de tipos de datos no básicos, pues a no ser que valgan null sus valores no se pueden determinar durante la compilación sino únicamente tras la ejecución de su constructor. La única excepción a esta regla son los tipos enumerados, cuyos valores se pueden determinar al compilar como se explicará cuando los veamos en el Tema 14: Enumeraciones
Todas las constantes son implícitamente estáticas, por lo se considera erróneo incluir el modificador static en su definición al no tener sentido hacerlo. De hecho, para leer su valor desde códigos externos a la definición de la clase donde esté definida la constante, habrá que usar la sintaxis <nombreClase>.<nombreConstante> típica de los campos static.
Por último, hay que tener en cuenta que una variable sólo puede ser definida como constante si es una variable local o un campo, pero no si es un parámetro.
Variables de sólo lectura
Dado que hay ciertos casos en los que resulta interesante disponer de la capacidad de sólo lectura que tienen las constantes pero no es posible usarlas debido a las restricciones que hay impuestas sobre su uso, en C# también se da la posibilidad de definir variables que sólo puedan ser leídas. Para ello se usa la siguiente sintaxis:
readonly <tipoConstante> <nombreConstante> = <valor>;
|
Estas variables superan la mayoría de las limitaciones de las constantes. Por ejemplo:
- No es obligatorio darles un valor al definirlas, sino que puede dárseles en el constructor. Ahora bien, una vez dado un valor a una variable readonly ya no es posible volverlo a modificar. Si no se le da ningún valor ni en su constructor ni en su definición tomará el valor por defecto correspondiente a su tipo de dato.
- No tienen porqué almacenar valores constantes, sino que el valor que almacenen puede calcularse durante la ejecución de la aplicación.
- No tienen porqué definirse como estáticas, aunque si se desea puede hacerse.
- Su valor se determina durante la ejecución de la aplicación, lo que permite la actualización de códigos cliente sin necesidad de recompilar. Por ejemplo, dado:
namespace Programa1 { public class Utilidad { public static readonly int X = 1; } }
namespace Programa2 { class Test { public static void Main() { System.Console.WriteLine(Programa1.Utilidad.X); } } }
|
En principio, la ejecución de este programa producirá el valor 1. Sin embargo, si cada espacio de nombres se compilan en módulos de código separados que luego se enlazan dinámicamente y cambiamos el valor de X, sólo tendremos que recompilar el módulo donde esté definido Programa1.Utilidad y Programa2.Test podrá ejecutarse usando el nuevo valor de X sin necesidad de recompilarlo.
Sin embargo, pese a las ventajas que las variables de sólo lectura ofrecen respecto a las constantes, tienen dos inconvenientes respecto a éstas: sólo pueden definirse como campos (no como variables locales) y con ellas no es posible realizar las optimizaciones de código comentadas para las constantes.