c# property Estático readonly vs const




static vs const c# (12)

He leído acerca de static readonly campos const y static readonly . Tenemos algunas clases que solo contienen valores constantes. Se utiliza para varias cosas alrededor de nuestro sistema. Así que me pregunto si mi observación es correcta:

¿Deben este tipo de valores constantes ser siempre static readonly para todo lo que es público? ¿Y solo usa const para valores internos / protegidos / privados?

¿Que recomiendas? ¿Es posible que incluso no use static readonly campos static readonly , sino que use las propiedades tal vez?


Algunas otras cosas

const int a

  • debe ser inicializado
  • La inicialización debe ser en tiempo de compilación

readonly int a

  • Se puede usar el valor por defecto, sin inicializar.
  • La inicialización puede ser en tiempo de ejecución

Yo usaría static readonly si el Consumidor está en un ensamblaje diferente. Tener a la const y al consumidor en dos montajes diferentes es una buena forma de dispararte en el pie .


Las constantes son como su nombre lo indica, los campos que no cambian y generalmente se definen de forma estática en el momento de la compilación en el código.

Las variables de solo lectura son campos que pueden cambiar bajo condiciones específicas.

Se pueden inicializar cuando se declaran por primera vez como una constante, pero generalmente se inicializan durante la construcción del objeto dentro del constructor.

No se pueden cambiar después de la inicialización, en las condiciones mencionadas anteriormente.

La lectura estática de solo lectura suena como una mala elección para mí, ya que, si es estática y nunca cambia, así que solo úsala constante pública, si puede cambiar, entonces no es una constante y luego, dependiendo de tus necesidades, puedes usar lectura -Sólo una variable regular o simplemente.

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.


Mi preferencia es usar const siempre que pueda, lo que, como se mencionó anteriormente, se limita a expresiones literales o algo que no requiere evaluación.

Si me caliento contra esa limitación, entonces retrocedo a la lectura estática solo , con una advertencia. Por lo general, usaría una propiedad estática pública con un captador y un campo de lectura estática privada de respaldo, como menciona Marc here .


Const : los valores de las variables const deben definirse junto con la declaración y después de eso no cambiarán. Las const son implícitamente estáticas, así que sin crear una instancia de clase podemos acceder a ellas. Esto tiene un valor en tiempo de compilación.

ReadOnly : valores 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.

Lectura estática solo : valores de variable estática de solo lectura que podemos definir mientras declaramos y solo a través del constructor estático pero no con ningún otro constructor. A 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. Por favor, revise 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/


Solo lectura estática : el valor se puede cambiar a través del constructor static 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, Función, tiempo de ejecución, etc., en ningún lugar).

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.

Puedes echar un vistazo a mi repo: tipos de propiedades C # .


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 readonly 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 readonly 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;
}

Dado 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, green, blue) = (r, g, 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 readonly 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, green, blue) = (r, g, 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.


Esto es solo un suplemento a las otras respuestas. No los repetiré (ahora cuatro años después).

Hay situaciones en las que una const y una no constante tienen semántica diferente. Por ejemplo:

const int y = 42;

static void Main()
{
  short x = 42;
  Console.WriteLine(x.Equals(y));
}

imprime True , mientras que:

static readonly int y = 42;

static void Main()
{
  short x = 42;
  Console.WriteLine(x.Equals(y));
}

escribe False

La razón es que el método x.Equals tiene dos sobrecargas, una que lleva un short ( System.Int16 ) y otra que toma un object ( System.Object ). Ahora la pregunta es si uno o ambos se aplican con mi argumento y .

Cuando y es una constante de compilación (literal), el caso const , se vuelve importante que exista una conversión implícita de int a short siempre que int sea ​​una constante, y siempre que el compilador C # verifique que su valor está dentro de El rango de un short (que es 42 ). Consulte Conversiones de expresiones constantes implícitas en la Especificación del lenguaje C #. Así que ambas sobrecargas tienen que ser consideradas. Se prefiere la sobrecarga Equals(short) (cualquier short es un object , pero no todos los object son short ). Entonces y se convierte a short , y se usa esa sobrecarga. Entonces Equals compara dos valores short de valores idénticos, y eso da true .

Cuando y no es una constante, no existe una conversión implícita de int a short . Eso es porque en general un int puede ser demasiado grande como para caber en un short . (Existe una conversión explícita , pero no dije Equals((short)y) , por lo que no es relevante). Vemos que solo se aplica una sobrecarga, Equals(object) . Así que y está encajonado para object . Entonces Equals va a comparar un System.Int16 con un System.Int32 , y dado que los tipos de tiempo de ejecución ni siquiera están de acuerdo, eso dará como resultado false .

Llegamos a la conclusión de que en algunos casos (raros), cambiar un miembro de tipo const a un campo de static readonly (o al contrario, cuando sea posible) puede cambiar el comportamiento del programa.


public static readonly campos de public static readonly son un poco inusuales; public static propiedades public static (con solo una get ) serían más comunes (quizás respaldadas por un campo de private static readonly ).

const valores const se graban directamente en el sitio de la llamada; esto es de doble filo:

  • es inútil si el valor se recupera en tiempo de ejecución, tal vez desde config
  • Si cambia el valor de una constante, debe reconstruir todos los clientes.
  • pero puede ser más rápido, ya que evita una llamada al método ...
  • ... que a veces podría haber sido incluido por el JIT de todos modos

Si el valor nunca cambia, entonces const es correcto - Zero etc., haga constantes razonables; p Aparte de eso, las propiedades static son más comunes.


Const: Const no es más que "constante", una variable cuyo valor es constante pero en tiempo de compilación. Y es obligatorio asignarle un valor. Por defecto, const es estático y no podemos cambiar el valor de una variable const en todo el programa.

Static ReadOnly: el valor de una variable de tipo Static Readonly puede asignarse en tiempo de ejecución o asignarse en tiempo de compilación y cambiarse en tiempo de ejecución. Pero el valor de esta variable solo se puede cambiar en el constructor estático. Y no se puede cambiar más. Puede cambiar solo una vez en tiempo de ejecución

Referencia: c-sharpcorner


Una cosa a tener en cuenta es que const se restringe a tipos primitivos / de valor (la excepción son las cadenas)


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 conjunto X expone una constante de la siguiente manera:

public const decimal ProgramVersion = 2.3;

Si el ensamblaje Y referencia a X y utiliza esta constante, el valor 2.3 se incluirá en el ensamblaje Y cuando se compile. Esto significa que si X se vuelve a compilar con la constante establecida en 2.4, Y seguirá utilizando el valor anterior de 2.3 hasta que Y 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 y, por lo tanto, no debe representarse como uno solo.







constants