He leído sobre consty static readonlycampos. 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 readonlypara todo lo público? ¿Y solo se usa constpara valores internos / protegidos / privados?
¿Que recomiendas? ¿Debería incluso no usar static readonlycampos, sino usar propiedades tal vez?

static readonly: intente usar un const dentro de unoIEnumeratorque desencadene un irrecuperableyieldy 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 readonlyno se puede usar en laswitch-casedeclaración comocasevariable,constse requiere para este propósito.static readonlyNo se puede utilizar como parámetro de atributo, tambiénRespuestas:
public static readonlylos campos son un poco inusuales;public staticlas propiedades (con solo aget) serían más comunes (quizás respaldadas por unprivate static readonlycampo).constlos valores se graban directamente en el sitio de la llamada; esto es de doble filo:Si el valor nunca cambia, entonces const está bien,
Zeroetc., haga consts razonables; p Aparte de eso, lasstaticpropiedades son más comunes.fuente
readonlycampos no se pueden usar en las declaraciones de cambio / caso, en cambio, necesita que lo seanconst.Lo usaría
static readonlysi el consumidor está en un ensamblaje diferente. Tener elconsty el Consumidor en dos conjuntos diferentes es una buena manera de dispararse en el pie .fuente
internal constopublic static readonlydependiendo 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 constsolo 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
ctorunico.Esto es solo un complemento de las otras respuestas. No los repetiré (ahora cuatro años después).
Hay situaciones en las que a
consty 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.Equalstiene 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 miyargumento.Cuando
yes una constante de tiempo de compilación (literal), elconstcaso, se vuelve importante que exista una conversión implícita deintashortsiempre queintsea una constante, y siempre que el compilador de C # verifique que su valor esté dentro del rango de ashort( cual42es) 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 (cualquierashortes unaobject, pero no todas loobjectsonshort). Entoncesyse convierte ashort, y se utiliza esa sobrecarga. LuegoEqualscompara dosshortde valor idéntico, y eso datrue.Cuando
yno es una constante, no existe conversión implícita deintashort. Eso es porque, en general, unintpuede 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. Entoncesyestá en caja paraobject. LuegoEqualsse va a comparar aSystem.Int16con 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
constmiembro de tipo a unstatic readonlycampo (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;dondeyse 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
constpodría usarse para otros tipos, excepto que debe inicializarse como nulo, lo que lo hace inútil :)System.Exception? :)constse pueden utilizar, sonsbyte,byte,short,ushort,int,uint,long,ulong,char,float,double,decimal,bool, además de cualquierenumtipo.constno se puede usar para otros tipos de valores, comoDateTimeoTimeSpanoBigInteger. Tampoco se puede usar para laIntPtrestructura (algunos lo consideran un tipo "primitivo"; el término tipo primitivo es confuso en C #). ↵↵ Seconstpuede 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.constusandodefault. Para losstructtipos, 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
staticconstructor 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
readonlypalabra clave es diferente de laconstpalabra clave. Unconstcampo solo se puede inicializar en la declaración del campo. Unreadonlycampo se puede inicializar en la declaración o en un constructor. Por lo tanto, losreadonlycampos pueden tener valores diferentes según el constructor utilizado. Además, aunque unconstcampo es una constante de tiempo de compilación, elreadonlycampo se puede usar para constantes de tiempo de ejecuciónReferencia breve y clara de MSDN aquí
fuente
constyreadonlyson similares, pero no son exactamente lo mismo.Un
constcampo es una constante de tiempo de compilación, lo que significa que ese valor se puede calcular en tiempo de compilación. Unreadonlycampo 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, unreadonlycampo no se puede cambiar.Por ejemplo, los
constmiembros 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
readonlypalabra 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
Xexpone una constante de la siguiente manera:Si el ensamblaje hace
YreferenciaXy usa esta constante, el valor 2.3 se integrará en el ensamblajeYcuando se compile. Esto significa que siXluego se vuelve a compilar con la constante establecida en 2.4,Yseguirá usando el valor anterior de 2.3 hastaYse 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.Emptyes 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