Pregunta

Por alguna razón, siempre he asumido que los campos readonly han asociado de arriba con ellos, por lo que pensé de que la pista mantenimiento de CLR de si o no un campo readonly se ha inicializado o no. La sobrecarga en este caso sería un poco de uso de memoria adicional para realizar un seguimiento del estado y un cheque al asignar un valor.

Tal vez asumido esto porque no sabía un campo readonly sólo podía ser inicializado dentro de un constructor o dentro de la propia declaración del campo y sin una verificación en tiempo de ejecución, que no sería capaz de garantizar que no está siendo asignado a varias veces en varios métodos. Pero ahora sé que esto, podría ser fácilmente comprobado estáticamente por el compilador de C #, ¿verdad? Así es que el caso?

Otra razón es que he leído que el uso de readonly tiene una 'ligera' impacto en el rendimiento, pero nunca entró en esta afirmación y no puedo encontrar información sobre este tema, por lo tanto, mi pregunta. No sé qué otras impacto en el rendimiento no puede ser, aparte de los controles en tiempo de ejecución.

Una tercera razón es que he visto que readonly se conserva en la IL compilado como initonly, así que lo que es la razón de que esta información sea de la IL si readonly no es más que una garantía por el compilador de C # que el campo es Nunca asignado a las afueras de un constructor o declaración?

Por otro lado, he descubierto que puede establecer el valor de un readonly int través de la reflexión sin el CLR lanzar una excepción, que no debería ser posible si readonly era un cheque en tiempo de ejecución.

Así que mi conjetura es: el 'readonlyness' es sólo una característica de tiempo de compilación, ¿alguien puede confirmar / negar esto? Y si lo es, ¿cuál es la razón para que esta información se incluirá en la IL?

¿Fue útil?

Solución

Hay que mirarlo desde el mismo punto de vista como los modificadores de acceso. Existen los modificadores de acceso en IL, pero ¿son realmente una comprobación en tiempo de ejecución? (1) No puedo asignar directamente los campos privados en tiempo de compilación, (2) que pueda asignarlos mediante la reflexión. Hasta ahora, parece sin verificación en tiempo de ejecución, como de sólo lectura .

Pero examinemos modificadores de acceso. Haga lo siguiente:

  1. Crear Asamblea A.dll con public class C
  2. Crear una b.exe Asamblea que hace referencia a A.dll. B.exe utiliza clase C.
  3. Construir los dos conjuntos. Correr b.exe funciona muy bien.
  4. Reconstruir A.dll pero conjunto de clases de C a interno. Reemplazar A.dll en el directorio del b.exe.

Ahora, corriendo b.exe produce una excepción de tiempo de ejecución.

Existen

Los modificadores de acceso en la IL así, ¿verdad? Entonces, ¿cuál es su propósito? El propósito es que los otros conjuntos que hacen referencia a un ensamblado de .NET necesitan saber lo que están autorizados a acceder y lo que no se les permite el acceso, tanto en tiempo de compilación y tiempo de ejecución.

Sólo lectura parece tener un propósito similar en IL . Se le dice a otros conjuntos de si se puede escribir en un campo de un tipo particular. Sin embargo, de sólo lectura no parece para tener ese mismo tiempo de ejecución compruebe que exhiben modificadores de acceso en mi ejemplo anterior. Parece que sólo lectura es un cheque en tiempo de compilación y no se produce en tiempo de ejecución. Echar un vistazo a una muestra de actuación aquí:. de sólo lectura rendimiento vs const

Una vez más, esto no significa que la IL es inútil. La IL se asegura de que se produce un error en tiempo de compilación en el primer lugar. Recuerde, cuando usted construye usted no construye frente a código, pero asambleas.

Otros consejos

Si está utilizando un estándar, variable de instancia, de sólo lectura llevará a cabo prácticamente idéntico a una variable normal. La IL añadido se convierte en una verificación de tiempo de compilación, pero es más o menos ignorada en tiempo de ejecución.

Si estás usando un miembro de sólo lectura estática, las cosas son un poco diferentes ...

Dado que el elemento de sólo lectura estática se establece durante el constructor estático, el JIT "sabe" que existe un valor. No hay memoria adicional -. Sólo lectura simplemente impide que otros métodos de ajuste de esto, pero eso es una verificación de tiempo de compilación

Desde el JIT sabe de esta persona nunca puede cambiar, se puede ser "codificado" en tiempo de ejecución, por lo que el efecto final es como tener un valor const. La diferencia es que va a tomar más tiempo durante el mismo tiempo JIT, ya que el compilador JIT tiene que hacer trabajo extra para hard-wire valor de la de sólo lectura en su lugar. (Esto va a ser muy rápido, sin embargo.)

Experto C ++ / CLI de Marcus Hegee tiene una razonablemente buena explicación de este .

Un punto importante, aunque no se menciona por cualquier otro respuestas es que cuando se accede a un campo de sólo lectura, o cuando se accede a cualquier propiedad, la petición se satisface mediante una copia de los datos. Si los datos en cuestión es un tipo de valor con más de 4-8 bytes de datos, el costo de esta copia adicional que a veces puede ser significativo. Tenga en cuenta que si bien hay un gran salto en el costo cuando estructuras crecen de 16 bytes a 17, estructuras pueden ser un poco más grande y todavía ser más rápido que las clases en muchas aplicaciones, si no se copian con demasiada frecuencia . Por ejemplo, si uno se supone que tiene un tipo que representa los vértices de un triángulo en el espacio tridimensional. Una aplicación sencilla sería una estructura que contiene una estructura con tres float para cada punto; Probablemente 36 bytes en total. Si los puntos, y las coordenadas de cada punto, son campos públicos mutables, se puede acceder a someTriangle.P1.X forma rápida y sencilla, sin tener que copiar todos los datos excepto la coordenada Y del vértice 1. Por otro lado, si P1 era una propiedad o una readonly campo, el compilador tendría que copiar P1 a una estructura temporal, y luego leer X de eso.

Incluso si sólo lectura sólo tenía efecto en tiempo de compilación, todavía sería necesario almacenar los datos en el conjunto (es decir, la IL). El CLR es un Común Idioma Tiempo de ejecución -. Clases escritas en un idioma pueden ser utilizadas y extendidas por otros idiomas

Debido a que cada compilador para el CLR no va a saber leer y compilar todos los demás idiomas, con el fin de preservar la semántica de los campos readonly, que los datos necesitan ser almacenados en el montaje para que los compiladores para otros idiomas se respetarla.

Por supuesto, el hecho de que el campo está marcado readonly significa el JIT puede hacer otras cosas, como la optimización (por ejemplo, usos en línea del valor), etc. Independientemente del hecho de que utilizó reflexión para cambiar el valor del campo, creando IL el que se modifica un campo initonly fuera del constructor correspondiente (ejemplo o estática, dependiendo del tipo de campo), dará lugar a un conjunto no verificable.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top