visual C#Proprietà automatiche-Perché devo scrivere? Get; impostato;"?




visual c# get set (8)

Se sia get sia set sono obbligatori nelle proprietà C #, perché devo preoccuparmi di specificare "get; set;" affatto?


Perché potresti volere una proprietà di sola lettura:

public int Foo { get; private set; }

O proprietà Write-only:

public int Foo { private get; set; }

Inoltre, poiché sin da C # 6.0 (in Visual Studio 2015, al momento di questa risposta disponibile nella versione Ultimate Preview) è possibile implementare una vera proprietà di sola lettura:

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

... al contrario di una soluzione attualmente imperfetta con la coppia getter / private setter pubblica:

public string Name { get; private set; }

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

Esempio di quanto sopra di seguito (compilato ed eseguibile online qui ).

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);
    }
}

Altre gustose notizie su C # 6.0 disponibili come anteprima video ufficiale qui .


Perché hai bisogno di un modo per distinguerlo dai campi semplici.

È anche utile avere diversi modificatori di accesso, ad es

public int MyProperty { get; private set; }

Dal momento che nessuno l'ha menzionato ... potresti rendere virtuale la proprietà automatica e sovrascriverla:

public virtual int Property { get; set; }

Se non ci fosse un get / set, come sarebbe stato ignorato? Si noti che è possibile ignorare il getter e non il setter :

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

Se la proprietà non ha avuto accessors, in che modo il compilatore lo separerebbe da un campo? E cosa lo separerebbe da un campo?


ERRORE: una proprietà o un indicizzatore non può essere passato come parametro out o ref

Se non hai specificato {get; set;} {get; set;} quindi il compilatore non saprebbe se si tratta di un campo o di una proprietà. Questo è importante perché mentre "sembrano" identici, il compilatore li tratta in modo diverso. Ad es. Chiamare "InitAnInt" sulla proprietà genera un errore.

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
    }
}

Non dovresti creare campi pubblici / Variabili sulle classi, non sai mai quando vorrai cambiarlo per ottenere e impostare i metodi di accesso, e quindi non sai quale codice stai per interrompere, specialmente se hai client che programmano contro la tua API.

Inoltre è possibile avere diversi modificatori di accesso per ottenere e impostare, ad esempio {get; set privato ;} rende pubblico e l'insieme privato alla classe dichiarante.


Beh, ovviamente hai bisogno di un modo per disambiguare i campi e le proprietà. Ma sono necessarie parole chiave davvero necessarie? Ad esempio, è chiaro che queste due dichiarazioni sono diverse:

public int Foo;
public int Bar { }

Potrebbe funzionare. Cioè, è una sintassi che un compilatore potrebbe plausibilmente dare un senso.

Ma poi si arriva a una situazione in cui un blocco vuoto ha un significato semantico. Sembra precario.


Ho pensato di condividere le mie scoperte su questo argomento.

Codificare una proprietà come la seguente, è una chiamata di collegamento .net 3.0 " auto-implementata ".

public int MyProperty { get; set; }

Questo ti risparmia un po 'di battitura. Il lungo modo di dichiarare una proprietà è come questo:

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

Quando si utilizza la "proprietà auto-implementata" il compilatore genera il codice per eseguire il collegamento e impostare su "k_BackingField". Di seguito è riportato il codice smontato utilizzando Reflector.

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

codice C # smontato da IL

Inoltre collega un metodo per il setter e il getter.

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

codice C # smontato da IL

Quando si dichiara una proprietà auto-implementata in sola lettura, impostando il setter su privato:

 public int MyProperty { get; private set; }

Tutto il compilatore contrassegna il " set " come privato. Il setter e il metodo getter dicono lo stesso.

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

codice C # smontato da IL

Quindi non sono sicuro del motivo per cui il framework richiede sia il get; e impostare; su una proprietà auto-implementata. Avrebbero potuto semplicemente non aver scritto il metodo set and setter se non fosse stato fornito. Ma potrebbe esserci qualche problema con il livello del compilatore che rende questo difficile, non lo so.

Se osservi la lunga strada della dichiarazione di una proprietà di sola lettura:

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

E poi guarda il codice smontato. Il setter non è affatto lì.

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

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

codice C # smontato da IL





automatic-properties