He leído sobre const
y static readonly
campos. Tenemos algunas clases que contienen solo valores constantes. Usado para varias cosas en nuestro sistema. Entonces me pregunto si mi observación es correcta:
¿Debería este tipo de valores constantes ser siempre static readonly
para todo lo público? ¿Y solo se usa const
para valores internos / protegidos / privados?
¿Que recomiendas? ¿Debería incluso no usar static readonly
campos, sino usar propiedades tal vez?
static readonly
: intente usar un const dentro de unoIEnumerator
que desencadene un irrecuperableyield
y obtendrá un temido "Error de compilador interno" . No probé el código fuera de Unity3D, pero confío en que sea un error mono o .NET . Sin embargo, es un problema de C # .static readonly
no se puede usar en laswitch-case
declaración comocase
variable,const
se requiere para este propósito.static readonly
No se puede utilizar como parámetro de atributo, tambiénRespuestas:
public static readonly
los campos son un poco inusuales;public static
las propiedades (con solo aget
) serían más comunes (quizás respaldadas por unprivate static readonly
campo).const
los valores se graban directamente en el sitio de la llamada; esto es de doble filo:Si el valor nunca cambia, entonces const está bien,
Zero
etc., haga consts razonables; p Aparte de eso, lasstatic
propiedades son más comunes.fuente
readonly
campos no se pueden usar en las declaraciones de cambio / caso, en cambio, necesita que lo seanconst
.Lo usaría
static readonly
si el consumidor está en un ensamblaje diferente. Tener elconst
y el Consumidor en dos conjuntos diferentes es una buena manera de dispararse en el pie .fuente
internal const
opublic static readonly
dependiendo de la visibilidad deseada.public const
(por ejemplo, cualquier cosa que forme parte de un estándar. Cada vez que trabajo con XML, hay un espacio de nombres con un montón depublic const string
). Pero en general,public const
solo debe usarse después de considerar las implicaciones correctamente.Pocas cosas más relevantes a tener en cuenta:
const int a
readonly int a
fuente
ctor
unico.Esto es solo un complemento de las otras respuestas. No los repetiré (ahora cuatro años después).
Hay situaciones en las que a
const
y a no constantes tienen una semántica diferente. Por ejemplo:imprime
True
, mientras que:escribe
False
.La razón es que el método
x.Equals
tiene dos sobrecargas, una que toma unshort
(System.Int16
) y otra que toma unobject
(System.Object
). Ahora la pregunta es si uno o ambos se aplican con miy
argumento.Cuando
y
es una constante de tiempo de compilación (literal), elconst
caso, se vuelve importante que exista una conversión implícita deint
ashort
siempre queint
sea una constante, y siempre que el compilador de C # verifique que su valor esté dentro del rango de ashort
( cual42
es) Consulte Conversiones implícitas de expresiones constantes en la Especificación del lenguaje C #. Por lo tanto, se deben considerar ambas sobrecargas. SeEquals(short)
prefiere la sobrecarga (cualquierashort
es unaobject
, pero no todas loobject
sonshort
). Entoncesy
se convierte ashort
, y se utiliza esa sobrecarga. LuegoEquals
compara dosshort
de valor idéntico, y eso datrue
.Cuando
y
no es una constante, no existe conversión implícita deint
ashort
. Eso es porque, en general, unint
puede ser demasiado grande para caber en unshort
. (Existe una conversión explícita , pero no lo dijeEquals((short)y)
, así que eso no es relevante). Vemos que solo se aplica una sobrecarga, laEquals(object)
única. Entoncesy
está en caja paraobject
. LuegoEquals
se va a comparar aSystem.Int16
con aSystem.Int32
, y dado que los tipos de tiempo de ejecución ni siquiera están de acuerdo, eso dará lugarfalse
.Concluimos que en algunos casos (raros), cambiar un
const
miembro de tipo a unstatic readonly
campo (o de otra manera, cuando eso sea posible) puede cambiar el comportamiento del programa.fuente
short x = 42;
legalizar la declaración . Porque allí tienes unint
, es decir, el literal42
, que se convierte implícitamente enshort x
. Pero entonces, podrían haber restringido esto a solo literales numéricos; sin embargo, eligieron permitir también cosas comoshort x = y;
dondey
se define comoconst int y = 42;
, y luego terminaron con esto.Una cosa a tener en cuenta es que const está restringido a tipos primitivos / de valor (la excepción son las cadenas)
fuente
const
podría usarse para otros tipos, excepto que debe inicializarse como nulo, lo que lo hace inútil :)System.Exception
? :)const
se pueden utilizar, sonsbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
,float
,double
,decimal
,bool
, además de cualquierenum
tipo.const
no se puede usar para otros tipos de valores, comoDateTime
oTimeSpan
oBigInteger
. Tampoco se puede usar para laIntPtr
estructura (algunos lo consideran un tipo "primitivo"; el término tipo primitivo es confuso en C #). ↵↵ Seconst
puede usar para todos los tipos de referencia . Si el tipo esstring
, se puede especificar cualquier valor de cadena. De lo contrario, el valor debe sernull
.const
usandodefault
. Para losstruct
tipos, es una instancia con todos sus miembros configurados con los valores predeterminados.Solo lectura estática : el valor se puede cambiar a través del
static
constructor en tiempo de ejecución. Pero no a través de la función miembro.Constante : por defecto
static
. El valor no se puede cambiar desde ningún lugar (Ctor, Function, runtime, etc., donde no).Solo lectura : el valor se puede cambiar a través del constructor en tiempo de ejecución. Pero no a través de la función miembro.
Puede echar un vistazo a mi repositorio: tipos de propiedad C # .
fuente
La
readonly
palabra clave es diferente de laconst
palabra clave. Unconst
campo solo se puede inicializar en la declaración del campo. Unreadonly
campo se puede inicializar en la declaración o en un constructor. Por lo tanto, losreadonly
campos pueden tener valores diferentes según el constructor utilizado. Además, aunque unconst
campo es una constante de tiempo de compilación, elreadonly
campo se puede usar para constantes de tiempo de ejecuciónReferencia breve y clara de MSDN aquí
fuente
const
yreadonly
son similares, pero no son exactamente lo mismo.Un
const
campo es una constante de tiempo de compilación, lo que significa que ese valor se puede calcular en tiempo de compilación. Unreadonly
campo 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, unreadonly
campo no se puede cambiar.Por ejemplo, los
const
miembros se pueden usar para definir miembros como:Dado que valores como 3.14 y 0 son constantes de tiempo de compilación. Sin embargo, considere el caso en el que define un tipo y desea proporcionar algunas instancias prefabricadas del mismo. 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 constantes, ya que los lados derechos no son constantes de tiempo de compilación. Se podría hacer esto con miembros estáticos regulares:
Pero entonces no hay nada para evitar que un cliente de Color se meta 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 función "solo lectura" aborda este escenario.
Simplemente introduciendo la
readonly
palabra clave en las declaraciones, preservamos la inicialización flexible al tiempo que evitamos que el código del cliente se pierda.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 normal.
Es posible utilizar una sola palabra clave para estos dos propósitos, pero esto conduce a problemas de versiones o problemas de rendimiento. Supongamos por un momento que usamos una sola palabra clave para esto (const) y un desarrollador escribió:
y un desarrollador diferente escribió un código que dependía de A:
Ahora, ¿puede el código generado depender del hecho de que AC es una constante de tiempo de compilación? Es decir, ¿puede el uso de AC simplemente ser reemplazado por el valor 0? Si dice "sí" a esto, eso significa que el desarrollador de A no puede cambiar la forma en que se inicializa AC; esto ata las manos del desarrollador de A sin permiso.
Si responde "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 al desarrollador de A especificar la intención. Esto permite un mejor comportamiento de versiones y también un mejor rendimiento.
fuente
Mi preferencia es usar const siempre que pueda, lo cual, como se mencionó anteriormente, está limitado a expresiones literales o algo que no requiere evaluación.
Si golpeo contra esa limitación, entonces recurro a la lectura estática solo , con una advertencia. En general, usaría una propiedad estática pública con un captador y un campo de solo lectura estático privado de respaldo, como Marc menciona aquí .
fuente
Referencia: c-sharpcorner
fuente
Un campo de solo lectura estático es ventajoso cuando se expone a otros ensamblajes un valor que podría cambiar en una versión posterior.
Por ejemplo, supongamos que el ensamblaje
X
expone una constante de la siguiente manera:Si el ensamblaje hace
Y
referenciaX
y usa esta constante, el valor 2.3 se integrará en el ensamblajeY
cuando se compile. Esto significa que siX
luego se vuelve a compilar con la constante establecida en 2.4,Y
seguirá usando el valor anterior de 2.3 hastaY
se vuelva a compilar. Un campo de solo lectura estático evita este problema.Otra forma de ver esto es que cualquier valor que pueda cambiar en el futuro no es constante por definición, por lo que no debe representarse como uno.
fuente
const:
solo lectura:
fuente
Const : los valores de la variable const deben definirse junto con la declaración y después de eso no cambiará. Los const son implícitamente estáticos, por lo que sin crear una instancia de clase podemos acceder a ellos. esto tiene un valor en tiempo de compilación
ReadOnly : valores variables de solo lectura que podemos definir al declarar y usar el constructor en tiempo de ejecución. las variables de solo lectura no pueden acceder sin instancia de clase.
Solo lectura estática estática: valores variables de solo lectura estática que podemos definir al declarar, así como solo a través del constructor estático pero no con cualquier otro constructor. Estas variables también podemos acceder sin crear una instancia de clase (como variables estáticas).
la lectura estática solo será una mejor opción si tenemos que consumir las variables en diferentes ensamblajes. Verifique los detalles completos en el siguiente enlace
https://www.stum.de/2009/01/14/const-strings-a-very-convenient-way-to-shoot-yourself-in-the-foot/
fuente
Hay una pequeña diferencia entre const y los campos de solo lectura estática en C # .Net
const debe inicializarse con valor en tiempo de compilación.
const es estático por defecto y debe inicializarse con un valor constante, que no puede modificarse más adelante. No se puede usar con todos los tipos de datos. Por ejemplo, DateTime. No se puede usar con el tipo de datos DateTime.
readonly puede declararse como estático, pero no es necesario. No es necesario inicializar en el momento de la declaración. Su valor se puede asignar o cambiar usando el constructor una vez. Por lo tanto, existe la posibilidad de cambiar el valor del campo de solo lectura una vez (no importa, si es estático o no), lo que no es posible con const.
fuente
Las constantes son como su nombre lo indica, campos que no cambian y generalmente se definen estáticamente en el momento de la compilación en el código.
Las variables de solo lectura son campos que pueden cambiar en condiciones específicas.
Pueden inicializarse cuando los declara por primera vez como una constante, pero generalmente se inicializan durante la construcción de objetos dentro del constructor.
No se pueden cambiar después de que se realizó la inicialización, en las condiciones mencionadas anteriormente.
La lectura estática de solo lectura me parece una mala elección ya que, si es estática y nunca cambia, así que solo utilícela const pública, si puede cambiar, entonces no es una constante y luego, dependiendo de sus necesidades, puede usar leer -solo o solo una variable regular.
Además, otra distinción importante es que una constante pertenece a la clase, ¡mientras que la variable de solo lectura pertenece a la instancia!
fuente
Una constante (que se determina en tiempo de compilación) se puede usar en casos en los que una lectura estática no puede, como en declaraciones de cambio o constructores de atributos. Esto se debe a que los campos de solo lectura solo se resuelven en tiempo de ejecución, y algunas construcciones de código requieren garantía de tiempo de compilación. Se puede calcular una estática de solo lectura en un constructor, que a menudo es algo esencial y útil. La diferencia es funcional, como debería ser su uso en mi opinión.
En términos de asignación de memoria, al menos con cadenas (que son un tipo de referencia), parece que no hay diferencia en que ambas están internadas y harán referencia a la única instancia internada.
Personalmente, mi valor predeterminado es de solo lectura estática, ya que tiene más sentido semántico y lógico para mí, especialmente porque la mayoría de los valores no son necesarios en el momento de la compilación. Y, por cierto, las estadísticas públicas de solo lectura no son inusuales o poco comunes, como dice la respuesta marcada: por ejemplo,
System.String.Empty
es una.fuente
Otra diferencia entre declarar const y static readonly está en la asignación de memoria.
Un campo estático pertenece al tipo de un objeto en lugar de a una instancia de ese tipo. Como resultado, una vez que se hace referencia a la clase por primera vez, el campo estático "vivirá" en la memoria por el resto del tiempo, y todas las instancias del tipo harán referencia a la misma instancia del campo estático.
Por otro lado, un campo constante "pertenece a una instancia del tipo.
Si la memoria de desasignación es más importante para usted, prefiera usar const . Si es velocidad, entonces use solo lectura estática .
fuente