2008-12-04 21 views

Respuesta

49

ERROR: una propiedad o indizador no se pueden pasar como out o ref parámetro

Si no se ha especificado {get; set;} entonces el compilador no sabría si es un campo o una propiedad. Esto es importante porque mientras "se ven" idénticos, el compilador los trata de manera diferente. p.ej. Llamar a "InitAnInt" en la propiedad genera un error.

class Test 
{ 
    public int n; 
    public int i { get; set; } 
    public void InitAnInt(out int p) 
    { 
     p = 100; 
    } 
    public Test() 
    { 
     InitAnInt(out n); // This is OK 
     InitAnInt(out i); // ERROR: A property or indexer may not be passed 
          // as an out or ref parameter 
    } 
} 

No debe crear pública campos/variables sobre las clases, nunca se sabe cuando se querrá cambiarlo tener & obtener descriptores de acceso set, y luego no saben qué código se va para romper, especialmente si tiene clientes que programan contra su API.

También puede tener diferentes modificadores de acceso para el conjunto get &, p. Ej. {obtener; privado establecer;} hace que el público y el conjunto sean privados para la clase declarante.

62

Debido a que es posible que desee una de sólo lectura propiedad:

public int Foo { get; private set; } 

o dado de única propiedad:

public int Foo { private get; set; } 
+3

También puede agregar todo tipo de modificadores, como protegidos, etc. – Tigraine

+0

Sí, y lo que otras personas dijeron ... necesita una forma de distinguir entre un campo y una propiedad. –

+1

Una pequeña nota al margen: existe el concepto de campos de solo lectura. El marco se asegurará de que estos solo se escriban una vez. Es diferente de setters privados o getters que se pueden escribir si tiene acceso. –

4

El compilador necesita saber si desea que se genere un captador y/o un colocador, o tal vez están declarando un campo.

16

Porque necesita alguna forma de distinguirlo de los campos simples.

También es útil tener diferentes modificadores de acceso, p. Ej.

public int MyProperty { get; private set; } 
+0

Pero los campos públicos son inútiles. –

+0

De acuerdo. La sintaxis probablemente se pueda atribuir en parte a que mr anders no quiera introducir una nueva palabra clave en el idioma. –

+1

Earwicker: Encontré campos públicos útiles en mi clase Vector2f: aceleraban mucho el programa (en comparación con las propiedades), y la clase es lo suficientemente simple como para no tener que cambiar la implementación. –

2

Si la propiedad no tiene accesores, ¿cómo lo separaría el compilador de un campo? ¿Y qué lo separaría de un campo?

16

Solo pensé en compartir mis hallazgos sobre este tema.

Codificando una propiedad como la siguiente, es una llamada de acceso directo .net 3.0 "propiedad auto implementada".

public int MyProperty { get; set; } 

Esto le ahorra algo de tipeo. El largo camino para declarar una propiedad es la siguiente:

private int myProperty; 
public int MyProperty 
{ 
    get { return myProperty; } 
    set { myProperty = value; } 
} 

Cuando se utiliza la “propiedad de auto-aplicado”, el compilador genera el código para cablear el obtener y establecer a algún “k_BackingField”. A continuación se muestra el código desmontado con Reflector.

public int MyProperty 
{ 
    [CompilerGenerated] 
    get 
    { 
     return this.<MyProperty>k__BackingField; 
    } 
    [CompilerGenerated] 
    set 
    { 
     this.<MyProperty>k__BackingField = value; 
    } 
} 

desmontado C# código de IL

también cables de hasta un método para la setter y getter.

[CompilerGenerated] 
public void set_MyProperty(int value) 
{ 
    this.<MyProperty>k__BackingField = value; 
} 
[CompilerGenerated] 
public int get_MyProperty() 
{ 
    return this.<MyProperty>k__BackingField; 
} 

desmontado C# código de IL

Cuando se declara una propiedad única de auto-aplicado leer, mediante el establecimiento de la incubadora a lo privado:

public int MyProperty { get; private set; } 

Todo el compilador hace bandera de la " establecer "como privado. El método setter y getter dicen lo mismo.

public int MyProperty 
{ 
    [CompilerGenerated] 
    get 
    { 
     return this.<MyProperty>k__BackingField; 
    } 
    private [CompilerGenerated] 
    set 
    { 
     this.<MyProperty>k__BackingField = value; 
    } 
} 

desensamblado del código de C de IL

así que no estoy seguro de por qué el marco requiere tanto el get; y establecer; en una propiedad implementada automáticamente. Podrían simplemente no haber escrito el método set y setter si no se hubiera proporcionado. Pero puede haber algún problema en el nivel del compilador que lo haga difícil, no lo sé.

Si nos fijamos en el largo camino de declarar una propiedad de sólo lectura:

public int myProperty = 0; 
public int MyProperty 
{ 
    get { return myProperty; } 
} 

y luego ver el código desensamblado. El colocador no está allí en absoluto.

public int Test2 
{ 
    get 
    { 
     return this._test; 
    } 
} 

public int get_Test2() 
{ 
    return this._test; 
} 

desensamblado del código de C de IL

+5

El método de conjunto privado es obligatorio con las propiedades automáticas, porque de lo contrario nunca sería posible establecer el valor en nada, lo cual no tendría sentido. Puede excluir al colocador de una propiedad que no sea automática porque el campo de respaldo proporciona una forma de cambiar el valor internamente. –

+0

Buen punto, eso es correcto. Como no tiene una variable privada, mientras utiliza una propiedad implementada automáticamente, tiene la posibilidad de establecer un valor si no estaba allí. –

2

Bueno, obviamente, necesita una forma de eliminar la ambigüedad entre los campos y propiedades. Pero, ¿son necesarias las palabras clave realmente necesarias? Por ejemplo, está claro que estas dos declaraciones son diferentes:

public int Foo; 
public int Bar { } 

Eso podría funcionar. Es decir, es una sintaxis que un compilador podría concebir.

Pero luego llegas a una situación en la que un bloque vacío tiene un significado semántico. Eso parece precario.

2

Puesto que nadie lo mencionó ... que podría hacer que el auto-propiedad virtual y anularlo:

public virtual int Property { get; set; } 

Si no había get/set, ¿cómo se puede reemplazar? Tenga en cuenta que se le permite override the getter and not the setter:

public override int Property { get { return int.MinValue; } } 
2

también, porque desde C# 6.0 (en Visual Studio 2015, en el momento de la disponible en versión Ultimate Vista previa de esta respuesta) se puede poner en práctica una verdadera propiedad de sólo lectura:

public string Name { get; } 
public string Name { get; } = "This won't change even internally"; 

... en lugar de solución imperfecta actualmente con captador pública/privada par colocador:

public string Name { get; private set; } 

public Constructor() { Name="As initialised"; } 
public void Method() { Name="This might be changed internally. By mistake. Or not."; } 

Ejemplo de lo anterior a continuación (compilado y executa ble en línea here).

using System; 

public class Propertier { 
    public string ReadOnlyPlease { get; private set; } 

    public Propertier() { ReadOnlyPlease="As initialised"; } 
    public void Method() { ReadOnlyPlease="This might be changed internally"; } 
    public override string ToString() { return String.Format("[{0}]",ReadOnlyPlease); } 
} 

public class Program { 
    static void Main() { 
     Propertier p=new Propertier(); 
     Console.WriteLine(p); 

//  p.ReadOnlyPlease="Changing externally!"; 
//  Console.WriteLine(p); 

     // error CS0272: The property or indexer `Propertier.ReadOnlyPlease' cannot be used in this context because the set accessor is inaccessible 
     // That's good and intended. 

     // But... 
     p.Method(); 
     Console.WriteLine(p); 
    } 
} 

Otras buenas noticias sobre C# 6.0 disponible como video de vista previa oficial here.

Cuestiones relacionadas