2010-03-19 17 views
54

Encontré un tema en MSDN que dice que sí, esto es posible.¿Es posible la propiedad de solo lectura y auto implementada?

Me hicieron una prueba que parece romper esta declaración:

using System; 

namespace Test 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Foo f = new Foo("1"); 
      Console.WriteLine(f.Bar); // prints 1 
      f.Test("2"); 
      Console.WriteLine(f.Bar);// successfully prints 2 
     } 
    } 

    class Foo 
    { 
     public Foo(string b) 
     { 
      this.Bar = b; 
     } 

     public string Bar { get; private set; } 

     public void Test(string b) 
     { 
      // this would be impossible for readonly field! 
      // next error would be occur: CS0191 or CS0191 
      // A readonly field cannot be assigned to (except in a constructor or a variable initializer) 
      this.Bar = b; 
     } 
    } 
} 

¿Dónde estoy mal?

+4

Creo que está probando el tipo incorrecto de solo lectura aquí. Su código solo dice que no tiene permitido establecer la barra de propiedades directamente desde ningún lugar fuera de la clase ni desde las subclases (instalador privado). Sus métodos de clase aún pueden cambiar la variable si el setter es privado. – dbemerlin

+1

ummm ... ¿qué pasa con 'public readonly string Bar;'? – peterchen

+0

@dbemerlin: estoy hablando solo de sentido de la palabra clave. No sobre los niveles de acceso. Hay un tema apropiado en MSDN: http://msdn.microsoft.com/en-us/library/ba0a1yw2.aspx. Creo que solo hay un tipo de solo lectura en C#. Todo lo demás es todo lo demás, no solo de lectura en C# :) – abatishchev

Respuesta

91

La respuesta a continuación fue escrito en 2010. En C# 6 (publicado en 2015) que puede escribir las propiedades implementadas automáticamente de sólo lectura:

// This can only be assigned to in a constructor 
public int Foo { get; } 

Tienes toda la razón. Las propiedades implementadas automáticamente de solo lectura correcta son actualmente imposibles. Haciendo que el colocador privada no es lo mismo, independientemente de lo que algunos libros y MSDN podrían decir :)

Si yo gobernaba el mundo, este no sería el caso. Cuando veo a algunos de los diseñadores de idiomas llamando al NDC 2010 en junio (¡por favor, acérquense!) Pretendo intentar persuadir, sobornar, engatusar y, en general, hacerme una molestia hasta que acepten. Es solo una característica de oblea delgada, después de todo.

cuanto a que el artículo de MSDN, el propio texto no dice que crea una propiedad de sólo lectura automática. Crea un tipo inmutable usando una propiedad automática, y eso es correcto. Los únicos bits problemáticos son los comentarios que dicen

// Read-only properties. 

... que definitivamente son incorrectos. El marco está de acuerdo con nosotros:

var prop = typeof(Contact).GetProperty("Name"); 
Console.WriteLine(prop.CanWrite); // Prints True 
+1

Una función * wafer-thin * se traduce en muchas personas-semanas de trabajo: http://blogs.msdn.com/ericlippert/archive/2003/10/28/53298.aspx – Brian

+0

@Brian: Es por eso que voy tener que persuadir, puentear, engatusar, etc. :) Pero en comparación con muchas otras características, creo que esto realmente * sería * pequeño. –

+26

No tiene que convencernos de que es una buena idea; sabemos que es una buena idea. Las preguntas son (1) ¿es esta la mejor característica posible que podemos hacer dado el presupuesto de tiempo y dinero que tenemos, y (2) podemos gastar ese presupuesto para resolver un aspecto más general, más difícil, menos "delgado" de la inmutabilidad , de que los accesorios inmutables son un caso especial simple?Cada característica estrecha de "propósito especial" que agregamos aumenta la complejidad de la gramática; queremos asegurarnos de obtener un buen valor en el futuro para esa complejidad adicional. –

1

conjunto privado no es lo mismo que readonly.

similares a los métodos o campos, la palabra clave private hace que la visibilidad de la incubadora a la disposición de la propia clase. Otros objetos no pueden usar el colocador, pero los métodos de la clase pueden llamarlo libremente. Por lo tanto, su código de prueba se compila y funciona bien.

Parece que los objetos externos como una propiedad readonly, pero no es de sólo lectura en la verdadera definición.

8

La propiedad es de sólo lectura fuera de la clase Foo. Creo que eso es a lo que apunta el artículo.

Pero no es lo mismo que marcar una variable con la palabra clave readonly.

6

Es confuso. Debe diferenciar entre solo lectura y C# readonly (lo que significa la palabra clave).

  • de solo lectura: significa que nadie de fuera puede escribir directamente, solo leer.
  • C# readonly: solo puede escribir en el constructor, nunca más.
+0

Llamaría a eso 'solo lectura' y 'solo lectura en C#' – abatishchev

+2

@abatischchev hay una palabra clave de solo lectura en C#, que era lo que quise decir –

+0

@persuade: Sí, estoy hablando de eso también. Quiero decir que algo en C# no es de solo lectura sin la palabra clave readonly. Es mejor llamarlo de otra manera – abatishchev

4

No, no es posible hacer una propiedad auto implementada de solo lectura.Para la página se conectó:

con propiedades de auto-aplicado, tanto un get y set de acceso se requieren

Un establecimiento no dispone de acceso set única lectura.

A property without a set accessor is considered read-only

1

La palabra clave de sólo lectura, en C# y VB, hacen lo mismo cuando se aplica a un campo. Lo hacen para que el campo solo se pueda asignar durante la inicialización estática (si está marcado como un campo estático/compartido) o durante el constructor.

C# no utiliza la palabra clave readonly para nada más.

La palabra clave ReadOnly en VB adquiere un significado diferente cuando se aplica a una propiedad. En este caso, simplemente significa que no hay una forma aceptable de asignar a la propiedad pública (internamente, el campo de respaldo puede ser modificado por otro código interno, por supuesto).

1

No se puede crear una propiedad auto implementada readonly. Si intenta compilar una clase con una propiedad de auto-aplicado obtendrá este error si no tiene, tanto obtener y definir:

'ProjectName.ClassName.Property.get' debe declarar un cuerpo porque no está marcado como abstracto o externo Las propiedades implementadas automáticamente deben definir los accesadores get y set.

Con la frase que comienza con 'Automáticamente' es la parte del error que nos ocupa.

Cuestiones relacionadas