2009-06-26 13 views
12

Mi proyecto contiene una gran cantidad de clases con propiedades cuyo campo de respaldo está marcado como "solo lectura", ya que solo se configuran en la construcción. Como una cuestión de estilo, me gusta usar auto-propiedades, ya que elimina una gran cantidad de código repetitivo y alienta el uso del miembro de la propiedad en lugar del campo de respaldo. Sin embargo, cuando uso una propiedad automática, pierdo la "capacidad de lectura" de mi campo de respaldo. Yo entiendo que el compilador/tiempo de ejecución es capaz de tomar ventaja de algunas mejoras en el rendimiento cuando un campo está marcado de esta manera, así que me gustaría ser capaz de marcar mi auto-propiedad como de sólo lectura, algo como esto:¿Es posible forzar una propiedad automática para utilizar un campo de respaldo de solo lectura?

[ReadOnly] 
public string LastName { get; } 

en lugar de

private readonly string _LastName; 
public string LastName 
{ 
    get 
    { 
     return _LastName; 
    } 
} 

¿Hay algún mecanismo disponible para hacer esto? De lo contrario, ¿es realmente útil la ganancia de rendimiento del campo de respaldo personalizado?

Exponer el campo como público es otra opción, supongo, parece incorrecto exponer un campo de esa manera. es decir,

public readonly string LastName; 
+1

Acepto que parece incorrecto exponer un campo público de solo lectura. Si alguna vez tuvo que cambiar a una propiedad más adelante, el cambio rompería la compatibilidad. –

+2

Como las respuestas se han anotado correctamente, no, no hay forma de hacer esto ahora. Esta es una característica que se solicita con frecuencia y, sin duda, ocupa un lugar destacado en la lista de posibles características nuevas para versiones hipotéticas futuras del idioma. Personalmente, me gustaría tener un conjunto completo de características relacionadas que fomenten la programación en un estilo inmutable; este sería solo uno de ellos. –

Respuesta

13

no tengo miedo, pero se puede hacer esto:

public string LastName { get; private set; } 

No es tan bueno como readonly, pero no demasiado malo.

+0

Es 'cadena de solo lectura Foo {get {return" bar ";} set;}' y 'cadena Foo {get {return" bar ";}}' equivalent? –

4

No, no lo es y, si fuera así, sería inútil sin ajustes significativos.

Un campo de solo lectura solo se puede establecer verificablemente desde un constructor. Una propiedad implementada automáticamente solo se puede configurar desde el setter generado. Estos son requisitos incompatibles y producirán código no verificable.

Sí, podría hacer que el compilador sea lo suficientemente inteligente como para ignorar al colocador e ir directamente al campo de respaldo en el constructor. Pero en el setter en sí mismo aún no sería verificable. El compilador necesitaría omitirlo del código generado así como producir una propiedad verdaderamente de solo lectura. Esto produce otra contradicción porque aún tendría que hacer una declaración de asignación en contra de la propiedad.

Foo() { 
    SomeProperty = "somevalue"; 
} 

En este caso, el código parece que está llamando a un colocador en una propiedad. Pero en realidad no se debe llamar a ningún setter ya que debe omitirse del código final.

EDITAR

Esto no quiere decir que no se puede hacer. Puede, pero requeriría un poco de trabajo de C#.

En particular, tendrían que proporcionar una forma de establecer el campo de respaldo de una propiedad que no puede tener un colocador. Hay varias formas en que esto se puede hacer.

  • dar a los usuarios el acceso al campo respaldo de una propiedad de auto-aplicado
  • Permitir la sintaxis de estilo de la moda a pesar de que no existe una incubadora y dejar que el compilador traducirlo a un acceso en campo bajo el capó
  • Inventar alguna sintaxis nueva

No estoy diciendo que estas sean buenas opciones, solo posibilidades de hacer que este tipo de característica funcione.

+0

Necesitaría una sintaxis alternativa para esto, pero me encantaría que fuera viable. Agregará una respuesta con eso ... –

+0

@Jon estuvo de acuerdo, modifiqué mi respuesta para decir "ajustes significativos" – JaredPar

+0

+1 para ir a los extremos y explicar por qué. Bastante interesante. – jasper

1

Prefiero el campo de respaldo real readonly, ya que esto garantiza que no cambiaré ese campo de respaldo después de la construcción.

1

No y no. No hay forma de hacerlo y no hay ganancia de rendimiento para los campos de respaldo de solo lectura.

+0

He entendido que 'static readonly' no permite que el JIT realice algunas optimizaciones, como nunca hacer copias del valor. – JulianR

+0

@JulianR - No hay beneficios de rendimiento por lo que sé. Consulte http://stackoverflow.com/questions/277010/what-are-the-benefits-to-marking-a-field-as-readonly-in-c –

+2

No se trata de rendimiento, se trata de una codificación segura. –

8

No, lamentablemente no hay forma de hacerlo. Personalmente hay dos cosas que creo que faltan en las propiedades implementadas automáticamente en C#: un valor predeterminado (que creo que estará en VB10) y propiedades de solo lectura que solo se pueden establecer en el constructor. En otras palabras, me gustaría ser capaz de hacer:

public class Foo 
{ 
    public string Tag { get; internal set; } = "Default value"; 

    // The "readonly" would imply "private" as it could only 
    // be set from a constructor in the same class 
    public int Value { get; readonly set; } 

    public Foo() 
    { 
     // Valid to set property here, but nowhere else 
     Value = 20; 
    } 
} 

Como se mencionó Jared, esto significaría cambiar las llamadas compilador del organismo emisor de la propiedad en las tareas de campo simples, y asegurarse de que sólo se produjeron en el constructor.

Esto haría que escribir tipos inmutables sea más simple. Desafortunadamente la situación no mejorará en C# 4. Esperemos que obtengamos algo como esto para C# 5 ...

+0

Mientras tanto, ¿se prefiere uno sobre el otro? Parece que tanto la auto-propiedad sin setter como la implementación del campo de respaldo de solo lectura proporcionan una implementación inmutable. ¿Es solo una cuestión de estilo después de eso? – JadeMason

+5

Personalmente me apego a un campo de respaldo de solo lectura a menos que sea un código desechable. Me gusta saber que es * adecuadamente * inmutable, incluso si accidentalmente intento establecerlo dentro de mi propio tipo. –

+0

Eugh! ¿Cómo puede un colocador ser de solo lectura? Tal vez public readonly int Value {get; conjunto; } –

3

A partir de C# 6.0 la respuesta es sí. Su ejemplo se puede escribir de la siguiente manera, y el compilador genera automáticamente un campo de solo lectura detrás de la propiedad. Esto se conoce como auto-propiedad getter-only.

public string LastName { get; } 

De https://msdn.microsoft.com/en-us/magazine/dn879355.aspx

Getter sólo auto-propiedades están disponibles en ambas estructuras y clase declaraciones, pero son especialmente importantes a causa de estructuras la guía de buenas prácticas que estructuras inmutables . En lugar de aproximadamente seis líneas necesarias para declarar una propiedad de solo lectura e inicializarla antes de C# 6.0, ahora una declaración de una sola línea y la asignación desde el constructor son todo lo que se necesita. Por lo tanto, la declaración de estructuras inmutables ahora no solo es el patrón de programación correcto para las estructuras, sino también el patrón más simple, un cambio muy apreciado de sintaxis anterior donde la codificación requería correctamente más esfuerzo.

Cuestiones relacionadas