2012-02-02 8 views
16

Existen muchas preguntas sobre este tema, pero ninguna (excepto one but still a short one) trata de la situación siguiente.Static solo contrasta const - diferentes conjuntos POV?

De C# 4 del libro:

enter image description here

Marc también escribió:

si cambia el valor de una constante, tiene que reconstruir todos los clientes

Pregunta:

1) ¿Por qué es eso? ¿Ambos son static readonly y const - static?

2) Donde en realidad se guardan los valores?

3) ¿Cómo hace un campo static readonly en realidad solve este problema "detrás de la escena"?

+2

Es porque el compilador "alineará" el valor de la constante, en lugar de hacer referencia a una variable que proviene de otro ensamblaje. – ken2k

+2

Nunca se supo de este comportamiento de consensos entre los ensamblajes. Buena pregunta –

Respuesta

21

no, a const es un const, no es estático, es un caso especial, con diferentes reglas; es única conjunto en tiempo de compilación (no en tiempo de ejecución), y se maneja de manera diferente

el punto crucial aquí es lo que los medios siguientes:

var foo = SomeType.StaticValue; 

vs

var bar = SomeType.ConstValue; 

en el primer caso, lee el valor en tiempo de ejecución desde SomeType, es decir, a través de ldsfld; sin embargo, en el segundo caso, se compilará con el valor, es decirsi ConstValue pasa a ser 123, entonces el segundo es idéntica a:

var bar = 123; 

en tiempo de ejecución, el hecho de que se trataba de SomeTypeno existe, como el valor (123) se evaluó por el compilador, y almacenado. Por lo tanto, necesita una reconstrucción para recoger nuevos valores.

Cambiando a static readonly significa que se conserva el "cargar el valor de SomeType".

Así lo siguiente:

static int Foo() 
{ 
    return Test.Foo; 
} 
static int Bar() 
{ 
    return Test.Bar; 
} 
... 
static class Test 
{ 
    public static readonly int Foo = 123; 
    public const int Bar = 456; 
} 

compila como:

.method private hidebysig static int32 Bar() cil managed 
{ 
    .maxstack 8 
    L_0000: ldc.i4 0x1c8 
    L_0005: ret 
} 

.method private hidebysig static int32 Foo() cil managed 
{ 
    .maxstack 8 
    L_0000: ldsfld int32 ConsoleApplication2.Test::Foo 
    L_0005: ret 
} 

Tenga en cuenta que en el Bar, la ldc está cargando un valor directamente (0x1c8 == 456), con Test completamente ido.

Para completar, la const es implementado con un campo estático, pero - es un literal campo, lo que significa: evaluado en el compilador, no en tiempo de ejecución.

.field public static literal int32 Bar = int32(0x1c8) 
.field public static initonly int32 Foo 
+0

gracias por la excelente respuesta, pero no const es implícitamente estática? –

+1

@Royi bien, * sí * en la medida en que se implementa en el IL como un '.field ... estático', y en el C# al que se accede como' TypeName.ConstName' - pero lo importante es la ** semántica **; y en términos de lo que significa la semántica, hay una gran diferencia entre acceder a un miembro estático regular (campo/prop) y acceder a un miembro de la estafa. –

4

Ya ha respondido su pregunta con la imagen que ha vinculado. const los campos se compilarán ("en línea") en el conjunto, como una simple búsqueda y reemplazo. static readonly significa un campo normal que no puede cambiar y existe solo una vez en la memoria, pero todavía se hace referencia a la ubicación de la memoria.

En .NET Framework, las constantes no tienen asignada una región de memoria, pero se consideran valores. Por lo tanto, nunca puede asignar una constante , pero cargar la constante en la memoria es más eficiente porque puede inyectarse directamente en la secuencia de instrucciones. Este elimina cualquier acceso a la memoria fuera de la memoria, mejorando la localidad de referencia . http://www.dotnetperls.com/optimization

6

1) const se acaba de resolver durante el tiempo de compilación con el valor que usted ha proporcionado. Mientras que static readonly es una variable estática.

2) static los valores se almacenan generalmente en un área especial en el montón llamado High Frequency Heap. Como dije anteriormente, las consts se sustituyen en tiempo de compilación.

3) por lo que es static readonly resolverá el problema porque leerá un valor variable en tiempo de ejecución, no un valor proporcionado en tiempo de compilación.

24

si cambia el valor de una constante, tiene que reconstruir todos los clientes

Esa no es la solución correcta. Si cambia el valor de una const, entonces no era una constante. Las constantes son por definición cosas que nunca cambian su valor. La idea de que usted cambie el valor de una constante significa que está haciendo algo lógicamente imposible, y por supuesto las cosas se romperán; estás haciendo algo que dijiste que no harías. Si va por ahí mintiendo al compilador, y duele cuando lo hace, entonces deja de mentir al compilador.

El precio del oro no es una constante. El nombre de tu banco no es una constante. El número de versión de su programa no es una constante. Estas cosas cambian, por lo que no las convierte en constantes. Las constantes son cosas como pi, o la cantidad de protones en un átomo de oro.

Las variables son cosas que pueden variar - es por eso que se llaman "variables". Las constantes son cosas que permanecen ... constantes. Si puede variar, conviértalo en una variable. Si es constante, hazlo constante. Es tan simple como eso.

¿por qué es eso? tanto static readonly como const son estáticos

Sure. ¿Qué tiene eso que ver con eso? "estático" en C# significa que "el elemento nombrado está asociado con el tipo, en lugar de con cualquier instancia particular del tipo". ("Estático" es por lo tanto una mala elección de términos; VB lo hace mejor con "compartido").

Si el nombre está asociado con el tipo o una instancia es irrelevante para la pregunta de si el nombre hace referencia a constante o variable.

donde en realidad los valores se guardan en ambos estáticos de solo lectura vsconst?

Cuando se utiliza un valor constante, el valor se "cuece en" dondequiera que se utilice. Eso es seguro porque nunca va a cambiar. Nunca va a cambiar porque es constante, y eso es lo que significa "constante".

Cuando utiliza una variable, el valor de la variable se busca en el tiempo de ejecución cada vez. "solo lectura" solo significa "esta variable solo se puede cambiar en el constructor de la clase o en el inicializador de campo". Todavía es una variable. (*)

cómo hacer un campo de forma estática de solo lectura, ¿realmente resuelve este problema detrás de la escena?

No ha indicado cuál es el problema, por lo que no sé qué problema está tratando de resolver.


(*) campos de solo lectura se consideran valores no constantes fuera el constructor, de manera que un campo de sólo lectura de tipo de valor mutable no se puede mutar, y por lo que no se puede tomar una ref a un solo lectura campo y luego mutar la referencia.

+1

¡Ahora entiendo lo que significa esta oración !: Si le miente al compilador, obtendrá su revancha -Henry Spencer – kokabi

+0

Su escritura es muy buena. ¿Por qué no escribir un gran libro sobre C#. ¡es mi sueño! – kokabi

+1

@ programmer1: ¡Gracias! Ayudé a Mark a escribir las últimas dos ediciones de Essential C#, pero la mayor parte de la escritura es suya. He pensado en escribir un libro propio de C#, pero es mucho trabajo. Además, escribo un blog sobre el diseño de C#. –

0

Supongo que podemos pensar en una constante como un valor codificado en nuestro código, pero con mejores ofertas de mantenimiento y usabilidad.

Cuestiones relacionadas