propiedad - readonly c# español
¿Cuál es la diferencia entre const y readonly? (29)
¿Cuál es la diferencia entre const
y readonly
y usas uno sobre el otro?
CONST
- La palabra clave const se puede aplicar a campos o variables locales
- Debemos asignar el campo const al momento de la declaración.
- No se asigna memoria porque el valor const se incrusta en el propio código IL después de la compilación. Es como encontrar todas las apariciones de la variable const y reemplazarlas por su valor. Por lo tanto, el código IL después de la compilación tendrá valores codificados en lugar de variables const.
- Const en C # son por defecto estático.
- El valor es constante para todos los objetos.
- Existe un problema con la versión de dll: esto significa que siempre que cambiemos una propiedad o una variable const pública, (de hecho, se supone que no se debe cambiar teóricamente), cualquier otra dll o ensamblaje que use esta variable se debe reconstruir
- Solo los tipos incorporados de C # pueden declararse como constantes
- El campo Const no se puede pasar como parámetro ref o out
Solo lectura
- La palabra clave readonly se aplica solo a campos, no a variables locales
- Podemos asignar un campo de solo lectura en el momento de la declaración o en el constructor, no en ningún otro método.
- Memoria dinámica asignada para campos de solo lectura y podemos obtener el valor en tiempo de ejecución.
- Readonly pertenece al objeto creado, por lo que solo se accede a través de una instancia de clase. Para que sea miembro de la clase, necesitamos agregar una palabra clave estática antes de solo lectura.
- El valor puede ser diferente dependiendo del constructor utilizado (ya que pertenece al objeto de la clase)
- Si declara un tipo no primitivo (tipo de referencia) como de solo lectura, la referencia es inmutable, no el objeto que contiene.
- Dado que el valor se obtiene en el tiempo de ejecución, no hay ningún problema de versión de dll con campos / propiedades de solo lectura.
- Podemos pasar el campo de solo lectura como parámetros de referencia o de salida en el contexto del constructor.
Constantes
- Las constantes son estáticas por defecto
- Deben tener un valor en tiempo de compilación (puede tener, por ejemplo, 3.14 * 2, pero no puede llamar a métodos)
- Podría ser declarado dentro de funciones
- Se copian en cada ensamblaje que los usa (cada ensamblaje obtiene una copia local de los valores)
- Puede ser utilizado en atributos
Campos de instancia de solo lectura
- Debe haber establecido un valor, para cuando el constructor salga.
- Se evalúan cuando se crea la instancia
Campos de solo lectura estáticos
- 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 en el momento en que se realiza el constructor estático
- No se recomienda poner ThreadStaticAttribute en estos (los constructores estáticos se ejecutarán en un solo hilo y establecerán el valor de su hilo; todos los demás hilos tendrán este valor sin inicializar)
¡Hay un gotcha con consts! Si hace referencia a una constante de otro conjunto, su valor se compilará directamente en el conjunto llamante. De esa manera, cuando actualice la constante en el ensamblaje al que se hace referencia, ¡no cambiará en el ensamblaje de llamada!
Ambos son constantes, pero una constante está disponible también en tiempo de compilación. Esto significa que un aspecto de la diferencia es que puede usar variables const como entrada para atribuir constructores, pero no variables de solo lectura.
Ejemplo:
public static class Text {
public const string ConstDescription = "This can be used.";
public readonly static string ReadonlyDescription = "Cannot be used.";
}
public class Foo
{
[Description(Text.ConstDescription)]
public int BarThatBuilds {
{ get; set; }
}
[Description(Text.ReadOnlyDescription)]
public int BarThatDoesNotBuild {
{ get; set; }
}
}
Aparte de la aparente diferencia de
- tener que declarar el valor en el momento de una definición para una
const
VS los valores dereadonly
se pueden calcular dinámicamente pero deben asignarse antes de que el constructor salga ... después de que se haya congelado. - Las const son implícitamente
static
. Utiliza una notaciónClassName.ConstantName
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
referencia a AssemblyA
y utiliza estos valores en el código. Cuando esto es compilado,
- en el caso del valor de
const
, es como un reemplazo de buscar, el valor 2 se "integra" en la IL delAssemblyB
. Esto significa que si mañana actualizaréI_CONST_VALUE
a 20 en el futuro.AssemblyB
todavía tendría 2 hasta que lo recompile . - en el caso del valor de
readonly
, es como unaref
a una ubicación de memoria. El valor no se incluye en la IL deAssemblyB
. Esto significa que si la ubicación de la memoria se actualiza,AssemblyB
obtiene el nuevo valor sin recompilación. Por lo tanto, siI_RO_VALUE
se actualiza a 30, solo necesita compilarAssemblyA
. Todos los clientes no necesitan ser recompilados.
Entonces, si está seguro de que el valor de la constante no cambiará, use una const
.
public const int CM_IN_A_METER = 100;
Pero si tiene una constante que puede cambiar (por ejemplo, precisión de precisión) ... o en caso de duda, use una readonly
.
public readonly float PI = 3.14;
Actualización: Aku necesita una mención porque él lo señaló primero. También necesito conectar donde aprendí esto. Efectivo C # - Bill Wagner
Const y readonly son similares, pero no son exactamente iguales. Un campo const es una constante de tiempo de compilación, lo que significa que ese valor se puede calcular en tiempo de compilación. Un campo de solo lectura habilita escenarios adicionales en los que se debe ejecutar algún código durante la construcción del tipo. Después de la construcción, un campo de solo lectura no se puede cambiar.
Por ejemplo, los miembros const se pueden usar para definir miembros como:
struct Test
{
public const double Pi = 3.14;
public const int Zero = 0;
}
ya que valores como 3.14 y 0 son constantes en tiempo de compilación. Sin embargo, considere el caso en el que define un tipo y desea proporcionar algunas instancias prefabricadas de él. Por ejemplo, es posible que desee definir una clase de Color y proporcionar "constantes" para colores comunes como Negro, Blanco, etc. No es posible hacer esto con miembros const, ya que los lados derechos no son constantes de tiempo de compilación. Uno podría hacer esto con miembros estáticos regulares:
public class Color
{
public static Color Black = new Color(0, 0, 0);
public static Color White = new Color(255, 255, 255);
public static Color Red = new Color(255, 0, 0);
public static Color Green = new Color(0, 255, 0);
public static Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) {
red = r;
green = g;
blue = b;
}
}
pero entonces no hay nada que impida que un cliente de Color se mezcle con él, tal vez intercambiando los valores de Blanco y Negro. No hace falta decir que esto causaría consternación a otros clientes de la clase Color. La característica "solo lectura" aborda este escenario. Simplemente introduciendo la palabra clave de solo lectura en las declaraciones, conservamos la inicialización flexible y evitamos que el código del cliente se pierda.
public class Color
{
public static readonly Color Black = new Color(0, 0, 0);
public static readonly Color White = new Color(255, 255, 255);
public static readonly Color Red = new Color(255, 0, 0);
public static readonly Color Green = new Color(0, 255, 0);
public static readonly Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) {
red = r;
green = g;
blue = b;
}
}
Es interesante observar que los miembros const son siempre estáticos, mientras que un miembro de solo lectura puede ser estático o no, al igual que un campo regular.
Es posible usar una sola palabra clave para estos dos propósitos, pero esto conduce a problemas de versión o problemas de rendimiento. Supongamos por un momento que usamos una sola palabra clave para esto (const) y un desarrollador escribió:
public class A
{
public static const C = 0;
}
y un desarrollador diferente escribió un código que se basaba en A:
public class B
{
static void Main() {
Console.WriteLine(A.C);
}
}
Ahora, ¿puede el código que se genera depender del hecho de que AC es una constante de compilación? Es decir, ¿puede el uso de AC simplemente ser reemplazado por el valor 0? Si dices "sí" a esto, entonces eso significa que el desarrollador de A no puede cambiar la forma en que AC se inicializa, lo que une las manos del desarrollador de A sin permiso. Si dice "no" a esta pregunta, se pierde una optimización importante. Quizás el autor de A esté seguro de que AC siempre será cero. El uso de const y readonly permite que el desarrollador de A especifique la intención. Esto permite un mejor comportamiento de las versiones y también un mejor rendimiento.
Creo que un valor de const
es el mismo para todos los objetos (y se debe inicializar con una expresión literal), mientras que el valor de readonly
puede ser diferente para cada instanciación ...
Hay un pequeño gotcha con solo lectura. Un campo de solo lectura se puede configurar varias veces dentro del constructor (es). Incluso si el valor se establece en dos constructores encadenados diferentes, todavía se permite.
public class Sample {
private readonly string ro;
public Sample() {
ro = "set";
}
public Sample(string value) : this() {
ro = value; // this works even though it was set in the no-arg ctor
}
}
Hay una diferencia notable entre los campos const y readonly en C # .Net
const es, por defecto, estático y debe inicializarse con un valor constante, que no se puede modificar más adelante. El cambio de valor no está permitido en los constructores, también. No se puede utilizar con todos los tipos de datos. Por ex DateTime. No se puede utilizar con el tipo de datos DateTime.
public const DateTime dt = DateTime.Today; //throws compilation error
public const string Name = string.Empty; //throws compilation error
public readonly string Name = string.Empty; //No error, legal
readonly se puede declarar como estático, pero no es necesario. No es necesario inicializar en el momento de la declaración. Su valor puede ser asignado o modificado utilizando el constructor. Por lo tanto, da ventaja cuando se utiliza como miembro de clase de instancia. Dos instancias diferentes pueden tener un valor diferente de campo de solo lectura. Por ej.
class A
{
public readonly int Id;
public A(int i)
{
Id = i;
}
}
Luego, el campo de solo lectura se puede inicializar con valores específicos instantáneos, de la siguiente manera:
A objOne = new A(5);
A objTwo = new A(10);
Aquí, la instancia objOne tendrá un valor de campo de solo lectura como 5 y objTwo tiene 10. Lo que no es posible usando const.
La diferencia clave es que Const es el equivalente en C de #DEFINE. El número se sustituye literalmente a-la precompilador. Readonly en realidad se trata como una variable.
Esta distinción es especialmente relevante cuando tiene el Proyecto A dependiendo de una constante pública del Proyecto B. Supongamos que la constante pública cambia. Ahora su elección de const / readonly impactará el comportamiento en el proyecto A:
Const: el proyecto A no captura el nuevo valor (a menos que se vuelva a compilar con la nueva const, por supuesto) porque se compiló con las constantes subtituladas en.
Solo lectura: el Proyecto A siempre le pedirá al proyecto B su valor variable, por lo que recogerá el nuevo valor de la constante pública en B.
Honestamente, le recomendaría que use solo lectura para casi todo, excepto las constantes verdaderamente universales (por ejemplo, Pi, Inches_To_Centimeters). Para cualquier cosa que pueda cambiar, digo usar solo.
Espero que esto ayude, Alan.
La diferencia es que el valor de un campo de solo lectura estático se establece en el tiempo de ejecución, por lo que puede tener un valor diferente para diferentes ejecuciones del programa. Sin embargo, el valor de un campo const se establece en una constante de tiempo de compilación.
Recuerde: para los tipos de referencia, en ambos casos (estático e instancia), el modificador de solo lectura solo le impide asignar una nueva referencia al campo. Específicamente no hace inmutable el objeto al que apunta la referencia.
Para obtener más información, consulte las Preguntas frecuentes sobre C # sobre este tema: http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx
Las variables constantes se declaran y se inicializan en tiempo de compilación. El valor no se puede cambiar después de las salas. Las variables de solo lectura se inicializarán solo desde el constructor Estático de la clase. Solo lectura se usa solo cuando queremos asignar el valor en tiempo de ejecución.
Las variables marcadas const son poco más que las macros #define fuertemente tipificadas, en el momento de la compilación las referencias de variables constantes se reemplazan con valores literales en línea. Como consecuencia, solo ciertos tipos de valores primitivos incorporados pueden usarse de esta manera. Las variables marcadas como de solo lectura pueden establecerse, en un constructor, en tiempo de ejecución y su capacidad de solo lectura se aplica también durante el tiempo de ejecución. Hay un costo de rendimiento menor asociado con esto, pero significa que puede usar solo lectura con cualquier tipo (incluso tipos de referencia).
Además, las variables const son inherentemente estáticas, mientras que las variables de solo lectura pueden ser específicas de la instancia, si se desea.
Otra gotcha .
Dado que const realmente solo funciona con tipos de datos básicos, si desea trabajar con una clase, puede sentirse "forzado" a usar ReadOnly. Sin embargo, ¡cuidado con la trampa! ReadOnly significa que no puede reemplazar el objeto con otro objeto (no puede hacer que se refiera a otro objeto). ¡Pero cualquier proceso que tenga una referencia al objeto es libre de modificar los valores dentro del objeto!
Así que no se confunda pensando que ReadOnly implica que un usuario no puede cambiar las cosas. No hay una sintaxis simple en C # para evitar que una instanciación de una clase tenga sus valores internos cambiados (que yo sepa).
Principalmente; puede asignar un valor a un campo de lectura estática solo a un valor no constante en el tiempo de ejecución, mientras que a una constante debe asignársele un valor constante.
ReadOnly: el valor se inicializará solo una vez desde el constructor de la clase.
const: se puede inicializar en cualquier función pero solo una vez
Sin embargo, otro gotcha: los valores de solo lectura se pueden cambiar mediante un código "tortuoso" a través de la reflexión.
var fi = this.GetType()
.BaseType
.GetField("_someField",
BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);
¿Puedo cambiar un campo privado heredado de solo lectura en C # usando la reflexión?
Solo para agregar, ReadOnly solo para tipos de referencia hace que la referencia sea de solo lectura, 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
}
}
Un miembro constante se define en tiempo de compilación y no se puede cambiar en tiempo de ejecución. Las constantes se declaran como un campo, utilizando la palabra clave const
y se deben inicializar como se declaran.
public class MyClass
{
public const double PI1 = 3.14159;
}
Un miembro de readonly
es como una constante en el sentido de que representa un valor que no cambia. La diferencia es que un miembro de readonly
se puede inicializar en tiempo de ejecución, en un constructor, y también se puede inicializar a medida que se declaran.
public class MyClass1
{
public readonly double PI2 = 3.14159;
//or
public readonly double PI3;
public MyClass2()
{
PI3 = 3.14159;
}
}
const
- No pueden ser declarados como
static
(son implícitamente estáticos) - El valor de la constante se evalúa en tiempo de compilación
- las constantes se inicializan solo en la declaración
solo lectura
- Pueden ser de nivel de instancia o estáticas.
- El valor se evalúa en tiempo de ejecución
- readonly se puede inicializar en declaración o por código en el constructor
Una const
tiene que ser codificada , de modo que como readonly
puede configurarse en el constructor de la clase.
Una constante es una constante de tiempo de compilación, mientras que solo lectura permite que un valor se calcule en tiempo de ejecución y se establezca en el constructor o inicializador de campo. Por lo tanto, una ''const'' siempre es constante pero ''readonly'' es de solo lectura una vez que se asigna.
Eric Lippert, del equipo C #, tiene más información sobre los diferentes tipos de inmutabilidad.
Una constante se compilará en el consumidor como un valor literal, mientras que la cadena estática servirá como una referencia al valor definido.
Como ejercicio, intente crear una biblioteca externa y consumirla en una aplicación de consola, luego altere los valores en la biblioteca y vuelva a compilarla (sin volver a compilar el programa del consumidor), coloque la DLL en el directorio y ejecute el EXE manualmente, debería encontrar que la cadena constante no cambia.
Una cosa para agregar a lo que la gente ha dicho anteriormente. Si tiene un conjunto que contiene un valor de solo lectura (por ejemplo, solo lectura MaxFooCount = 4;), puede cambiar el valor que ven los conjuntos que llaman al enviar una nueva versión de ese conjunto con un valor diferente (por ejemplo, solo lectura MaxFooCount = 5;)
Pero con una constante, se incluiría en el código de la persona que llama cuando se compila.
Si ha alcanzado este nivel de competencia en C #, está listo para el libro de Bill Wagner, C # efectivo: 50 maneras específicas de mejorar su C # que responde a esta pregunta en detalle (y otras 49 cosas).
Uno de los miembros del equipo en nuestra oficina proporcionó la siguiente guía sobre cuándo usar const, static y readonly:
- Use const cuando tenga una variable de un tipo que puede saber en tiempo de ejecución (cadena literal, int, double, enums, ...) que desea que todas las instancias o consumidores de una clase tengan acceso a donde el valor no debe cambiar.
- Use estática cuando tenga datos que desea que todas las instancias o consumidores de una clase tengan acceso a donde el valor puede cambiar.
- Use la lectura estática solo cuando tiene una variable de un tipo que no puede saber en el tiempo de ejecución (objetos) que desea que todas las instancias o consumidores de una clase tengan acceso a donde el valor no debe cambiar.
- Use readonly cuando tenga una variable de nivel de instancia que sabrá en el momento de la creación del objeto que no debería cambiar.
Una nota final: un campo const es estático, pero lo inverso no es verdadero.
Esto lo explica . Resumen: la constante debe inicializarse en el momento de la declaración, solo se puede inicializar en el constructor (y, por lo tanto, tener un valor diferente según el constructor utilizado).
EDITAR: Vea la parte superior de Gishu para la sutil diferencia.
Aquí hay otro enlace que muestra cómo const no es segura para la versión, o relevante para los tipos de referencia.
Resumen :
- El valor de su propiedad const se establece en tiempo de compilación y no puede cambiar en tiempo de ejecución
- Const no se puede marcar como estático: la palabra clave indica que son estáticos, a diferencia de los campos de solo lectura que sí pueden.
- Const no puede ser nada excepto tipos de valor (primitivos)
- La palabra clave readonly marca el campo como inmutable. Sin embargo, la propiedad se puede cambiar dentro del constructor de la clase
- La única palabra clave de solo lectura también se puede combinar con estática para que actúe de la misma manera que una constante (al menos en la superficie). Hay una marcada diferencia cuando miras el IL entre los dos
- los campos const están marcados como "literal" en IL mientras que readonly es "initonly"
const
: no se puede cambiar en ninguna parte
readonly
: este valor solo se puede cambiar en el constructor. No se puede cambiar en las funciones normales.
Constante
Necesitamos proporcionar el valor al campo const cuando está definido. El compilador luego guarda el valor de la constante en los metadatos del ensamblaje. Esto significa que una constante se puede definir solo para el tipo primitivo como boolean, char, byte, etc. Las constantes siempre se consideran miembros estáticos, no miembros de instancia.
Solo lectura
Los campos de solo lectura solo se pueden resolver en tiempo de ejecución. Eso significa que podemos definir un valor para un valor utilizando el constructor para el tipo en el que se declara el campo. El compilador realiza la verificación de que los campos de solo lectura no se escriben con ningún otro método que no sea el constructor.
Más sobre ambos explicados aquí en este artículo.
Solo lectura : el valor se puede cambiar a través de Ctor en tiempo de ejecución. Pero no a través de la función miembro
Constante : Por defecto estático. El valor no se puede cambiar desde ningún lugar (Ctor, Función, tiempo de ejecución, etc., en ningún lugar)