¿Cuál es la diferencia entre constante y solo lectura en C#?
¿Cuál es la diferencia entre const
y readonly
en C#?
¿Cuándo usarías uno sobre el otro?
Aparte de la aparente diferencia de
- tener que declarar el valor en el momento de una definición para los valores
const
VSreadonly
se puede calcular dinámicamente, pero debe asignarse antes de que salga el constructor. Después de eso se congela. const
son implícitamentestatic
. Utiliza unaClassName.ConstantName
notación para acceder a ellos.
Hay una diferencia sutil. Considere una clase definida en AssemblyA
.
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly int I_RO_VALUE;
public Const_V_Readonly()
{
I_RO_VALUE = 3;
}
}
AssemblyB
hace referencia AssemblyA
y utiliza estos valores en el código. Cuando esto se compila:
- en el caso del
const
valor, es como un buscar-reemplazar. El valor 2 está "integrado" en elAssemblyB
IL. Esto significa que si mañana actualizoI_CONST_VALUE
a 20,AssemblyB
todavía tendré 2 hasta que lo vuelva a compilar . - en el caso del
readonly
valor, es comoref
una ubicación de memoria. El valor no está integrado enAssemblyB
el IL de . Esto significa que si se actualiza la ubicación de la memoria,AssemblyB
se obtiene el nuevo valor sin necesidad de volver a compilarlo. Entonces, siI_RO_VALUE
se actualiza a 30, solo necesita compilarAssemblyA
y no es necesario volver a compilar todos los clientes.
Entonces, si está seguro de que el valor de la constante no cambiará, utilice un const
.
public const int CM_IN_A_METER = 100;
Pero si tiene una constante que puede cambiar (precisión de egwrt) o en caso de duda, utilice un archivo readonly
.
public readonly float PI = 3.14;
Actualización: Aku necesita una mención porque él lo señaló primero. También necesito mencionar dónde aprendí esto: C# efectivo - Bill Wagner
¡Hay un problema con las constantes! Si hace referencia a una constante de otro ensamblado, su valor se compilará directamente en el ensamblado que llama. De esa manera, cuando actualice la constante en el ensamblado al que se hace referencia, ¡no cambiará en el ensamblado que llama!
Constantes
- Las constantes son estáticas por defecto
- Deben tener un valor en el momento de la compilación (puede tener, por ejemplo, 3.14 * 2, pero no puede llamar a métodos)
- Podría declararse dentro de funciones
- Se copian en cada ensamblado que los utiliza (cada ensamblado obtiene una copia local de los valores)
- Se puede utilizar en atributos.
Campos de instancia de solo lectura
- Debe tener un valor establecido, cuando el constructor salga
- Se evalúan cuando se crea la instancia.
Campos estáticos de solo lectura
- Se evalúan cuando la ejecución del código llega a la referencia de clase (cuando se crea una nueva instancia o se ejecuta un método estático)
- Debe tener un valor evaluado cuando finalice el constructor estático.
- No se recomienda poner ThreadStaticAttribute en estos (los constructores estáticos se ejecutarán en un solo subproceso y establecerán el valor para su subproceso; todos los demás subprocesos tendrán este valor sin inicializar)
Solo para agregar, readonly
para los tipos de referencia solo hace que la referencia solo lea, no los valores. Por ejemplo:
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};
public UpdateReadonly()
{
I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
I_RO_VALUE = new char[]{'V'}; //will cause compiler error
}
}