¿Cuáles son los beneficios de tener una variable miembro declarada como de solo lectura? ¿Es solo protección contra alguien que cambia su valor durante el ciclo de vida de la clase o el uso de esta palabra clave resulta en mejoras de velocidad o eficiencia?
295
readonly
campos de tipos de estructura imponen una penalización de rendimiento en comparación con los campos mutables que simplemente no están mutados, ya que la invocación de cualquier miembro de unreadonly
campo de tipo de valor hará que el compilador haga una copia del campo e invoque el miembro de eso.Respuestas:
La
readonly
palabra clave se utiliza para declarar una variable miembro como constante, pero permite que el valor se calcule en tiempo de ejecución. Esto difiere de una constante declarada con elconst
modificador, que debe tener su valor establecido en tiempo de compilación. Utilizandoreadonly
puede establecer el valor del campo en la declaración o en el constructor del objeto del que es miembro el campo.Úselo también si no desea tener que volver a compilar archivos DLL externos que hacen referencia a la constante (ya que se reemplaza en tiempo de compilación).
fuente
No creo que haya ganancias de rendimiento al usar un campo de solo lectura. Es simplemente una comprobación para garantizar que una vez que el objeto esté completamente construido, ese campo no pueda apuntar a un nuevo valor.
Sin embargo, "solo lectura" es muy diferente de otros tipos de semántica de solo lectura porque el CLR lo aplica en tiempo de ejecución. La palabra clave readonly se compila en .initonly, que es verificable por el CLR.
La verdadera ventaja de esta palabra clave es generar estructuras de datos inmutables. Las estructuras de datos inmutables por definición no se pueden cambiar una vez construidas. Esto hace que sea muy fácil razonar sobre el comportamiento de una estructura en tiempo de ejecución. Por ejemplo, no hay peligro de pasar una estructura inmutable a otra porción aleatoria de código. Nunca pueden cambiarlo, por lo que puede programar de manera confiable contra esa estructura.
Aquí hay una buena entrada sobre uno de los beneficios de la inmutabilidad: Subprocesamiento
fuente
No hay beneficios aparentes de rendimiento al usar
readonly
, al menos ninguno que haya visto mencionado en ninguna parte. Es solo para hacer exactamente lo que sugiere, para evitar la modificación una vez que se ha inicializado.Por lo tanto, es beneficioso porque te ayuda a escribir código más robusto y más legible. El beneficio real de cosas como esta viene cuando trabajas en equipo o por mantenimiento. Declarar algo como
readonly
es similar a poner un contrato para el uso de esa variable en el código. Piense en ello como agregar documentación de la misma manera que otras palabras clave comointernal
oprivate
, está diciendo "esta variable no debe modificarse después de la inicialización", y además la está aplicando .Entonces, si crea una clase y marca algunas variables de miembros
readonly
por diseño, entonces evita que usted u otro miembro del equipo cometa un error más adelante cuando están expandiendo o modificando su clase. En mi opinión, es un beneficio que vale la pena tener (a costa de la complejidad adicional del lenguaje, como menciona doofledorfer en los comentarios).fuente
Para ponerlo en términos muy prácticos:
Si usa una constante en dll A y dll B hace referencia a esa constante, el valor de esa constante se compilará en dll B. Si vuelve a implementar dll A con un nuevo valor para esa constante, dll B seguirá utilizando el valor original.
Si utiliza un solo lectura en las referencias dll A y dll B que solo leen, esa lectura siempre se buscará en tiempo de ejecución. Esto significa que si vuelve a implementar dll A con un nuevo valor para esa lectura solamente, dll B usará ese nuevo valor.
fuente
const
puede tener una mejora en el rendimientoreadonly
. Aquí hay una explicación un poco más profunda con el código: dotnetperls.com/readonlyreadonly
campos. No puede almacenar unnew object();
en ayconst
eso tiene sentido porque no puede hornear cosas sin valor como referencias en otros ensamblajes durante el tiempo de compilación sin cambiar la identidad.Existe un caso potencial en el que el compilador puede realizar una optimización del rendimiento en función de la presencia de la palabra clave de solo lectura.
Esto solo se aplica si el campo de solo lectura también está marcado como estático . En ese caso, el compilador JIT puede asumir que este campo estático nunca cambiará. El compilador JIT puede tener esto en cuenta al compilar los métodos de la clase.
Ejemplo típico: su clase podría tener un campo estático de solo lectura IsDebugLoggingEnabled que se inicializa en el constructor (por ejemplo, basado en un archivo de configuración). Una vez que se compilan los métodos reales JIT, el compilador puede omitir partes enteras del código cuando el registro de depuración no está habilitado.
No he comprobado si esta optimización se implementa realmente en la versión actual del compilador JIT, por lo que esto es solo especulación.
fuente
Tenga en cuenta que solo lectura solo se aplica al valor en sí mismo, por lo que si está utilizando un tipo de referencia solo lectura solo protege la referencia de ser cambiada. El estado de la instancia no está protegido por readonly.
fuente
No olvide que hay una solución alternativa para
readonly
configurar los campos fuera de cualquier constructor que useout
parámetros.Un poco desordenado pero:
Más discusión aquí: http://www.adamjamesnaylor.com/2013/01/23/Setting-Readonly-Fields-From-Chained-Constructors.aspx
fuente
out
..Sorprendentemente, solo lectura puede resultar en un código más lento, como descubrió Jon Skeet al probar su biblioteca Noda Time. En este caso, una prueba que se ejecutó en 20 segundos tomó solo 4 segundos después de eliminar solo lectura.
https://codeblog.jonskeet.uk/2014/07/16/micro-optimization-the-surprising-inefficiency-of-readonly-fields/
fuente
readonly struct
en C # 7.2, el beneficio de hacer que el campo no sea de solo lectura desaparece.Si tiene un valor predefinido o precalculado que debe permanecer igual durante todo el programa, entonces debe usar constante, pero si tiene un valor que debe proporcionarse en el tiempo de ejecución pero una vez asignado debe permanecer igual en todo el programa, debe usar solo lectura. por ejemplo, si tiene que asignar la hora de inicio del programa o si tiene que almacenar un valor proporcionado por el usuario en la inicialización del objeto y tiene que restringirlo de más cambios, debe usar solo lectura.
fuente
Agregar un aspecto básico para responder esta pregunta:
Las propiedades se pueden expresar como de solo lectura al omitir el
set
operador. Por lo tanto, en la mayoría de los casos no necesitará agregar lareadonly
palabra clave a las propiedades:En contraste con eso: los campos necesitan la
readonly
palabra clave para lograr un efecto similar:Por lo tanto, una ventaja de marcar un campo como
readonly
puede ser lograr un nivel de protección contra escritura similar a una propiedad sinset
operador, sin tener que cambiar el campo a una propiedad, si por alguna razón, se desea.fuente
Tenga cuidado con las matrices privadas de solo lectura. Si estos están expuestos a un cliente como un objeto (puede hacer esto para la interoperabilidad COM como lo hice), el cliente puede manipular los valores de la matriz. Use el método Clone () cuando devuelva una matriz como un objeto.
fuente
ReadOnlyCollection<T>
lugar de una matriz.ImmutableArray<T>
, lo que evita el boxeo a una interfaz (IReadOnlyList<T>
) o el ajuste en una clase (ReadOnlyCollection
). Tiene un rendimiento comparable a las matrices nativas: blogs.msdn.microsoft.com/dotnet/2013/06/24/…Puede haber un beneficio de rendimiento en WPF, ya que elimina la necesidad de costosas propiedades de dependencia. Esto puede ser especialmente útil con colecciones
fuente
Otra parte interesante del uso de marcado de solo lectura puede ser proteger el campo de la inicialización en singleton.
por ejemplo en el código de csharpindepth :
readonly juega un pequeño papel en la protección del campo Singleton para que no se inicialice dos veces. Otro detalle es que para el escenario mencionado no puede usar const porque const fuerza la creación durante el tiempo de compilación, pero singleton hace la creación en tiempo de ejecución.
fuente
readonly
puede inicializarse en la declaración u obtener su valor solo del constructor. A diferencia deconst
esto, debe inicializarse y declararse al mismo tiempo.readonly
tiene todoconst
, más inicialización del constructorcódigo https://repl.it/HvRU/1
fuente