¿Qué es el {get; conjunto; } sintaxis en C #?

577

Estoy aprendiendo ASP.NET MVC y puedo leer documentos en inglés, pero realmente no entiendo lo que está sucediendo en este código:

public class Genre
{
    public string Name { get; set; }
}

¿Qué significa esto { get; set; }?

kn3l
fuente
44
En general recuerde: los colocadores hacen que su objeto sea mutable, una mala idea. getters viola "Dile a un objeto qué hacer, no le pidas información y manipúlalo tú mismo". Entonces, en general, no agregue setters y getters por defecto. Los necesitará, a menudo, pero siempre debe encontrar una necesidad real antes de agregarlos. En particular, los setters casi nunca deberían usarse en el código de producción (Esfuércese por la inmutabilidad siempre que sea posible, y cuando se necesita una mutación, debe pedirle que mute por usted, no establecer un valor).
Bill K
8
Solo para agregar algo ... Si no pones {get; set;}estás creando un Campo pero si pones el {get; set;}estás creando una Propiedad . Tener una propiedad podría facilitar algunas cosas, especialmente cuando se trabaja con Reflection.
Seichi
@Seichi usando un get-setter también crea un campo, pero este está oculto, declarado como privado y modificado por las propiedades creadas automáticamente; todo eso hecho por el compilador.
Jonathan Ramos
1
¿Las propiedades automotrices no son contrarias al propósito de campos privados ?
mireazma

Respuestas:

567

Es una llamada propiedad automática, y es esencialmente una abreviatura de lo siguiente (el compilador generará un código similar):

private string name;
public string Name
{
    get
    {
        return this.name;
    }
    set
    {
        this.name = value;
    }
}
Klaus Byskov Pedersen
fuente
93
Klaus, ¿puedes explicar qué pasará con este código? Podría beneficiarse de una explicación más exhaustiva.
TylerH
3
Entonces, solo para estar seguro: es como si sobrecargara el =operador, pero solo para un elemento en particular, ¿verdad?
Hola Ángel,
99
¿Por qué necesitamos las var. Privadas? :-/ vergüenza.
Oliver Dixon
2
@TylerH El motivo de la variable privada es la encapsulación, el get / set proporciona una "puerta" para obtener o establecer la variable. Aunque hay muchas razones para no usar get / setters porque la "puerta" puede romper la encapsulación de la variable privada. (no debería ser accesible)
Alexander
44
Puede ser obvio, pero quiero aclarar que la taquigrafía no es literalmente una taquigrafía para eso. Es decir, no namese crea una variable privada . Si trató de hacer referencia a esta variable privada dentro de la clase, fallará. No estoy seguro de cómo lo hace C #, pero se comporta como si hubiera una variable privada sin nombre, a la que no puede acceder en su código.
Denziloe
432

Entonces, según tengo entendido, { get; set; }es una "propiedad automática" que, al igual que @Klaus y @Brandon dijeron, es una forma abreviada de escribir una propiedad con un "campo de respaldo". Entonces en este caso:

public class Genre
{
    private string name; // This is the backing field
    public string Name   // This is your property
    {
        get => name;
        set => name = value;
    }
}

Sin embargo, si eres como yo, hace aproximadamente una hora, no entiendes realmente qué son las propiedades y los accesorios , y tampoco tienes la mejor comprensión de algunas terminologías básicas. MSDN es una gran herramienta para aprender cosas como esta, pero no siempre es fácil de entender para los principiantes. Así que voy a tratar de explicar esto más en profundidad aquí.

gety setson accesores , lo que significa que pueden acceder a datos e información en campos privados (generalmente desde un campo de respaldo ) y generalmente lo hacen desde propiedades públicas (como puede ver en el ejemplo anterior).

No se puede negar que la declaración anterior es bastante confusa, así que veamos algunos ejemplos. Digamos que este código se refiere a géneros de música. Entonces dentro de la clase Género, vamos a querer diferentes géneros de música. Digamos que queremos tener 3 géneros: Hip Hop, Rock y Country. Para hacer esto, usaríamos el nombre de la Clase para crear nuevas instancias de esa clase.

Genre g1 = new Genre(); //Here we're creating a new instance of the class "Genre"
                        //called g1. We'll create as many as we need (3)
Genre g2 = new Genre();
Genre g3 = new Genre();

//Note the () following new Genre. I believe that's essential since we're creating a
//new instance of a class (Like I said, I'm a beginner so I can't tell you exactly why
//it's there but I do know it's essential)

Ahora que hemos creado las instancias de la clase Genre, podemos establecer los nombres de los géneros utilizando la propiedad 'Name' que se estableció arriba.

public string Name //Again, this is the 'Name' property
{ get; set; } //And this is the shorthand version the process we're doing right now 

Podemos establecer el nombre de 'g1' en Hip Hop escribiendo lo siguiente

g1.Name = "Hip Hop";

Lo que está sucediendo aquí es algo complejo. Como dije antes, gety setacceda a información de campos privados a los que de otro modo no podría acceder. getsolo puede leer información de ese campo privado y devolverla. setsolo puede escribir información en ese campo privado. Pero al tener una propiedad con ambos gety setpodemos hacer ambas funciones. Y al escribir g1.Name = "Hip Hop";, estamos utilizando específicamente la setfunción de nuestra propiedad Nombre

setusa una variable implícita llamada value. Básicamente, lo que esto significa es que cada vez que ves "valor" dentro set, se refiere a una variable; la variable "valor". Cuando escribimos g1.Name =estamos usando =para pasar la valuevariable que en este caso es "Hip Hop". Así que esencialmente puedes pensarlo así:

public class g1 //We've created an instance of the Genre Class called "g1"
{
    private string name;
    public string Name
    {
        get => name;
        set => name = "Hip Hop"; //instead of 'value', "Hip Hop" is written because 
                              //'value' in 'g1' was set to "Hip Hop" by previously
                              //writing 'g1.Name = "Hip Hop"'
    }
}

Es importante tener en cuenta que el ejemplo anterior no está escrito en el código. Es más un código hipotético que representa lo que está sucediendo en segundo plano.

Así que ahora que hemos establecido el Nombre de la instancia g1 de Genre , creo que podemos obtener el nombre escribiendo

console.WriteLine (g1.Name); //This uses the 'get' function from our 'Name' Property 
                             //and returns the field 'name' which we just set to
                             //"Hip Hop"

y si ejecutamos esto, entraríamos "Hip Hop"en nuestra consola.

Entonces, para el propósito de esta explicación, también completaré el ejemplo con resultados

using System;
public class Genre
{
    public string Name { get; set; }
}

public class MainClass
{
    public static void Main()
    {
        Genre g1 = new Genre();
        Genre g2 = new Genre();
        Genre g3 = new Genre();

        g1.Name = "Hip Hop";
        g2.Name = "Rock";
        g3.Name = "Country";

        Console.WriteLine ("Genres: {0}, {1}, {2}", g1.Name, g2.Name, g3.Name);
    }
}

Salida:

"Genres: Hip Hop, Rock, Country"
Josie Thompson
fuente
18
Personalmente, solo lo comentaría como talset{name = value;} // 'value' here is equal to "Hip Hop"
maksymiuk
2
@iLoveUnicorns, está ahí con el propósito de abstracción de datos . El campo de respaldo es el que contiene los datos reales. La definición de propiedad en realidad define cómo se accede a los datos con los métodos gety set. El enlace que proporcioné tiene una excelente cita de John Guttag en la parte superior de la página. Recomendaría leer su libro o incluso tomar este curso en línea gratuito
Josie Thompson
2
No podemos utilizar: public class Genre{public string Name;} en lugar de: public class Genre{ public string Name { get; set; }}. Quiero decir, ¿por qué necesitamos {get; conjunto; }?
user2048204
1
Parece que mi preocupación ya se ha hecho eco. Si declara de esta manera: "public string Name {get; set;}" y accede de esta manera: g1.Name = "Hip Hop"; - Entonces, ¿dónde está la orientación del objeto? Ni siquiera necesito el llamado "campo de respaldo". El campo de respaldo ni siquiera existe, en lo que a mí respecta. Porque solo accedo al campo público. Y si el campo público es "público", entonces no cumple con OO. Volvamos a COBOL.
Baruch Atta el
1
Gran respuesta, pero si estamos siendo pedantes, "set" es un mutador, no un descriptor de acceso.
pythlang
100

Esas son propiedades automáticas

Básicamente, otra forma de escribir una propiedad con un campo de respaldo.

public class Genre
{
    private string _name;

    public string Name 
    { 
      get => _name;
      set => _name = value;
    }
}
Brandon
fuente
77
¿Qué se llama "campo de respaldo"?
kn3l
44
@stackunderflow: el campo de respaldo es donde se almacenan los datos. (lo que se devuelve al usar gety persiste al usar set). Al igual que el armario para el cual gety setabre la puerta.
Grant Thomas
55
@stackunderflow: en esta respuesta, el campo de respaldo es _name. En la propiedad automática, el campo de respaldo está oculto.
Justin
36

Esta es la forma corta de hacerlo:

public class Genre
{
    private string _name;

    public string Name
    {
      get => _name;
      set => _name = value;
    }
}
froeschli
fuente
33

Es un acceso directo para exponer miembros de datos como públicos para que no necesite crear explícitamente un miembro de datos privado. C # creará un miembro de datos privados para usted.

Podría hacer públicos sus miembros de datos sin usar este acceso directo, pero si decidiera cambiar la implementación del miembro de datos para tener algo de lógica, necesitaría romper la interfaz. En resumen, es un atajo para crear código más flexible.

Kelsey
fuente
2
Kelsey: ¿podría explicar cómo esta sintaxis hace que sea un código más "flexible"? No lo veo Si agregara alguna "lógica" al setter o getter, en el caso de ether (con o sin datos privados) aún rompería la interfaz, tal como está, y necesitaría algo de codificación.
Baruch Atta el
18

Básicamente, es un atajo de:

class Genre{
    private string genre;
    public string getGenre() {
        return this.genre;
    }
    public void setGenre(string theGenre) {
        this.genre = theGenre;
    }
}
//In Main method
genre g1 = new Genre();
g1.setGenre("Female");
g1.getGenre(); //Female
Jirson Tavera
fuente
55
Esto no responde la pregunta. El OP estaba hablando de propiedades.
theB
66
Conozco las propiedades Get and Set, es un ejemplo que ayuda a comprender mejor
Jirson Tavera
10

Es una propiedad implementada automáticamente para C #.

Daniel A. White
fuente
1
Eh ... ¿Esto significa que mantiene una referencia nula a la cadena y luego carga su valor desde una ubicación estándar cuando get; set;se llama?
Aurum Aquila
1
Sí, se mantiene nullcomo cualquier stringvariable hastasomeInstanceOfGenere.Name = "someValue"
Daniel A. White
6

Son los accesores para el Nombre de propiedad pública.

Los usaría para obtener / establecer el valor de esa propiedad en una instancia de Genre.

TimCodes.NET
fuente
6

Esa es una propiedad implementada automáticamente. Básicamente es una forma abreviada de crear propiedades para una clase en C #, sin tener que definir variables privadas para ellas. Normalmente se usan cuando no se requiere lógica adicional al obtener o establecer el valor de una variable.

Puede leer más en la Guía de programación de propiedades de implementación automática de MSDN .

Dusda
fuente
6
  • El patrón get / set proporciona una estructura que permite agregar lógica durante la configuración ('set') o recuperación ('get') de una instancia de propiedad de una clase instanciada, que puede ser útil cuando se requiere cierta lógica de instanciación para propiedad.

  • Una propiedad solo puede tener un descriptor de acceso 'get', que se hace para que esa propiedad sea de solo lectura

  • Al implementar un patrón get / set, se usa una variable intermedia como contenedor en el que se puede colocar un valor y extraer un valor. La variable intermedia suele estar prefijada con un guión bajo. Esta variable intermedia es privada para garantizar que solo se pueda acceder a través de sus llamadas get / set. Vea la respuesta de Brandon, ya que su respuesta demuestra las convenciones de sintaxis más comúnmente utilizadas para implementar get / set.

Chris Halcrow
fuente
5

Esto significa que si crea una variable de tipo Género, podrá acceder a la variable como una propiedad

Genre oG = new Genre();
oG.Name = "Test";
David Brunelle
fuente
55
Cuando no usa propiedades implementadas automáticamente, aún puede acceder a ella de esta manera. es decir, AIP no se trata de acceso desde afuera, sino de declaración dentro de una clase.
abatishchev
4

Dicha { get; set; }sintaxis se denomina propiedades automáticas, sintaxis de C # 3.0

Debe usar Visual C # 2008 / csc v3.5 o superior para compilar. Pero puede compilar resultados que se dirijan a .NET Framework 2.0 (no se requieren tiempo de ejecución ni clases para admitir esta característica).

linquizar
fuente
4

En Visual Studio, si define una propiedad Xen una clase y desea usar esta clase solo como un tipo, después de construir su proyecto, recibirá una advertencia que dice "El campo X nunca se asigna y siempre tendrá su valor predeterminado valor " .

Añadiendo una { get; set; }a Xla propiedad, no se va a esta advertencia.

Además, en Visual Studio 2013 y versiones superiores, al agregar { get; set; }puede ver todas las referencias a esa propiedad.

ingrese la descripción de la imagen aquí

Omid Ebrahimi
fuente
4

Es básicamente una taquigrafía. Puede escribir public string Name { get; set; }como en muchos ejemplos, pero también puede escribirlo:

private string _name;

public string Name
{
    get { return _name; }
    set { _name = value ; } // value is a special keyword here
}

¿Por qué se usa? Se puede usar para filtrar el acceso a una propiedad, por ejemplo, no desea que los nombres incluyan números.

Dejame darte un ejemplo:

private class Person {
    private int _age;  // Person._age = 25; will throw an error
    public int Age{
        get { return _age; }  // example: Console.WriteLine(Person.Age);
        set { 
            if ( value >= 0) {
                _age = value; }  // valid example: Person.Age = 25;
        }
    }
}

Oficialmente se llama Propiedades de implementación automática y es un buen hábito leer la ( guía de programación ). También recomendaría el video tutorial C # Propiedades: ¿Por qué usar "get" y "set" ?

Randel
fuente
2

Get set son modificadores de acceso a la propiedad. Obtener lee el campo de propiedad. Set establece el valor de la propiedad. Obtener es como acceso de solo lectura. Establecer es como acceso de solo escritura. Para usar la propiedad como lectura, se deben usar get y set.

Ashraf Abusada
fuente
1
Creo que get set no son modificadores de acceso, de hecho son accesores. Los modificadores de acceso son como: público, privado, interno, etc.
Rohit Arora
1

Get se invoca cuando la propiedad aparece en el lado derecho (RHS) El conjunto se invoca cuando la propiedad aparece en el lado izquierdo (LHS) del símbolo '='

Para una propiedad implementada automáticamente, el campo de respaldo funciona detrás de la escena y no es visible.

Ejemplo:

public string Log { get; set; }

Mientras que para una propiedad no implementada automáticamente, el campo de respaldo es inicial, visible como una variable de ámbito privado.

Ejemplo:

private string log;

public string Log
{
    get => log;
    set => log = value;
}

Además, vale la pena señalar aquí que el 'getter' y el 'setter' pueden usar los diferentes 'campos de respaldo'

Bala
fuente
Esto no parece responder a la pregunta formulada.
TylerH
Se proporciona una pista sobre cuándo se invoca get & set. Todas las respuestas mencionadas anteriormente dan la impresión de que el campo de respaldo para get & set es el mismo. Pero este no es el caso. Entonces mi respuesta es muy relevante para la pregunta principal. Espero que estés de acuerdo conmigo.
Bala
Para una propiedad autogenerada, que es de lo que se trata la pregunta, no puede haber diferentes campos de respaldo utilizados para el captador y el definidor; solo hay un campo de respaldo. Para una propiedad no automática (sobre la cual la pregunta no pregunta) puede que ni siquiera conceptualmente haya un campo de respaldo. Además, puede escribir un programa con un getter en el lado izquierdo de un operador de asignación y uno con un setter en el lado derecho de un operador de asignación. Entonces, no solo toda esta información no responde a la pregunta, sino que también está mal.
Servicio
0

Definir las variables privadas.

Dentro del constructor y carga los datos

He creado Constante y cargo los datos de constante a la clase Lista seleccionada.

public  class GridModel
{
    private IEnumerable<SelectList> selectList;
    private IEnumerable<SelectList> Roles;

    public GridModel()
    {
        selectList = from PageSizes e in Enum.GetValues(typeof(PageSizes))
                       select( new SelectList()
                       {
                           Id = (int)e,
                           Name = e.ToString()
                       });

        Roles= from Userroles e in Enum.GetValues(typeof(Userroles))
               select (new SelectList()
               {
                   Id = (int)e,
                   Name = e.ToString()
               });
    }

  public IEnumerable<SelectList> Pagesizelist { get { return this.selectList; } set { this.selectList = value; } } 
  public IEnumerable<SelectList> RoleList { get { return this.Roles; } set { this.Roles = value; } }
  public IEnumerable<SelectList> StatusList { get; set; }

}
Hari Lakkakula
fuente
0

Una propiedad es como una capa que separa la variable privada de otros miembros de una clase. Desde el mundo exterior parece que una propiedad es solo un campo, se puede acceder a una propiedad usando .Property

public class Person
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string FullName => $"{FirstName} {LastName}";
}

public class Person
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string FullName { get { return $"{FirstName} {LastName}"; } }
}

FullName es una propiedad. El que tiene flecha es un atajo. Desde el mundo exterior, podemos acceder a FullName de esta manera:

var person = new Person();
Console.WriteLine(person.FullName);

A las personas que llaman no les importa cómo implementó FullName. Pero dentro de la clase puedes cambiar FullName lo que quieras.

Consulte la documentación de Microsoft para obtener una explicación más detallada:

https://docs.microsoft.com/en-us/dotnet/csharp/properties

MING WU
fuente