2009-07-20 10 views
12

En C#, ¿la configuración de un campo como de solo lectura reduce el uso de memoria?¿"leer solo" (C#) reduce el uso de memoria?

es decir

DBRepository _db = new DBRepository(); 

vs

readonly DBRepository _db = new DBRepository(); 

Simplemente curioso. Gracias.

Respuesta

19

Esto significa que no se puede asignar a la misma, excepto en el punto de declaración o en un constructor. Tampoco puede pasarlo como un parámetro ref o out a un método.

Editar: basado en el comentario a continuación. El siguiente campo es readonly porque desea que las personas que llaman tengan acceso directo de lectura al string.Empty, pero no desea que lo configuren en otra cosa.

public sealed class String 
{ 
    public static readonly string Empty = ""; 
} 

También, a veces cuando tengo un List<> o Dictionary<> como un campo en una clase, voy a declarar que readonly para indicar que yo quiero trabajar con sus miembros (incluso añadir y quitar elementos, etc.) pero nunca quiero asignarle un objeto List o Dictionary diferente.

Una edición más: Asegúrese de leer sobre el campo obsoleto Path.InvalidPathChars (en la sección de comentarios) para mostrar un problema grave que puede ocurrir cuando no se comprende qué es y qué no es readonly.

+0

Una pregunta en una pregunta. Si es de solo lectura, ¿no reduce la memoria para lo que es un buen uso político de solo lectura en los campos? – pedrofernandes

+6

@ pho3nix: Erm, ¿qué hay de aplicar las prácticas de diseño? (Si una variable no debe modificarse, ¡no permita que se modifique!) – Noldorin

+0

Gracias por la respuesta rápida. – Chaddeus

0

readonly es útil en caso de que quiera usar un objeto como clave. Esta clave no debe cambiar, de lo contrario no podrá acceder a lo que le da acceso.

Por ejemplo; 1) con eventos en un sitio ASP.NET, puede usar la colección Eventos en un Control. En su control, mantendría un campo de solo lectura para referirse a los manejadores de eventos en la colección. 2) En multi-pisando, es posible que necesite sincronizar el acceso. Esto se puede hacer para combinar la declaración de bloqueo con un objeto de solo lectura en el que bloquear.

5

No. readonly y const tienen básicamente la misma finalidad: evitar asignaciones a los valores en tiempo de ejecución. Sin embargo, tienen usos semánticamente diferentes.

sólo lectura frente const

Un campo const se evalúa en compilar tiempo y sólo se puede inicializar en la declaración, mientras que un campo readonly se evalúa en plazo tiempo y se puede inicializar tanto en los constructores y en el sitio de declaración.

Además, un valor de campo const se almacena como parte de los metadatos y, por lo tanto, se inicializa en el constructor correspondiente de la clase que lo declaró mientras que los campos readonly se computarán en tiempo de ejecución.

5

¡SÍ!

¿Sí? ¡Sí! ¿Cómo? Sencillo. Un campo de solo lectura no puede obtener un nuevo valor, por lo que no puede crear un segundo DBRepository y asignarlo a este campo. Si no es de solo lectura, puede escribir código que reasignará un nuevo valor a este campo.Y durante el tiempo transcurrido entre la reasignación y el momento en que el recolector de basura borre su valor anterior, tendrá un poco más de memoria en uso. Además, si la limpieza del DBRepository tiene una pérdida de memoria, la reasignación de nuevos valores a este campo provocará múltiples pérdidas de memoria.

Una situación donde tal pérdida de memoria podría ocurrir es esto: 1) Asigne un valor a _db. 2) Asigna el valor de _db a otro campo. 3) Usted reasigna un nuevo valor a _db. En este momento, tendrá dos objetos DBRepository en la memoria porque todavía se hace referencia al viejo objeto desde otro objeto. Por lo tanto, el objeto antiguo no se liberará hasta que el segundo campo lo libere.

Pero esto es muy quisquilloso y bastante raro. La respuesta "No" es más apropiada. No use "ReadOnly" para guardar memoria porque la estaría usando por el motivo equivocado. Use "ReadOnly" para asegurarse de que otros no reasignen un valor a este campo. (Básicamente, estoy diciendo que puede reducir el uso de memoria ...)

0

La respuesta no está escrito desde la perspectiva de un buen rendimiento centró codificador que ya conoce todos los trucos y trampas por ejemplo .:

  1. No LINQ in tight loops. De Verdad. Ninguna. Nunca.
  2. eche sus enumeraciones de enteros antes de la comparación
  3. Cuidado con las estructuras del tipo valor
  4. 'nuevo' es el nuevo Grue
  5. CLRProfiler es su amigo
  6. Otros perfiladores pondrán tiempo de construcción de variables en lugares extraños

La respuesta Sí es muy relevante para un codificador que no conoce las trampas del diseño de C#, o que se ha tragado el coolade "Profiling is evil".

Inicializo un lote (quizás incluso MUCHO) de matrices y matrices en nuestro código. He notado que la inicialización diferida con: if (variable == nulo) // variable = nueva Variable()

parece menos eficaz que construir desde el principio. Como readonly te obliga a construir en el constructor, obtienes los beneficios de la localización de datos en la memoria y te impide hacer otras cosas desastrosas de "compilar y reemplazar en tiempo de ejecución". C# puede ahogarse horriblemente en el recolector de basura.

C# nos permite escribir muy fácilmente terriblemente código de memoria. malloc fue una forma de obligarnos a pensar en (de) la asignación. De la misma manera, solo nos obliga a pensar en ello.

Ejecute CLRProfiler, vea usted mismo la cantidad de spam de memoria que realiza. Si ha estado escribiendo HPC sin una disciplina casi sobrehumana, lo más probable es que esté enviando correo no deseado por correo no deseado y de solo lectura puede ayudar a evitar que lo haga.

Dicho esto, si no está escribiendo el código HPC, la optimización prematura es la raíz de todo lo que se aprende sobre la arquitectura de la máquina. Oh, no, espera ... quise decir mal, según la doctrina estándar. Todos saludan la doctrina estándar.

Cuestiones relacionadas