Preferisco le proprietà con o senza campi privati?

14

Il codice base in cui sto lavorando ora ha la convenzione di utilizzare campi privati e proprietà pubbliche. Ad esempio, molte classi hanno i loro membri definiti in questo modo:

// Fields
private double _foo;
private double _bar;
private double _baz;

// Properties
public double Foo
{
    get{ return _foo; }
    set{ _foo = value; }
}

public double Bar
{
    get{ return _bar; }
    set{ _bar = value; }
}

public double Baz
{
    get{ return _baz; }
}

So che possono essere riscritti senza le loro proprietà private interne:

public double Foo{ get; set; }
public double Bar{ get; set; }
public double Baz{ get; private set; }

Vorrei qualche input su questo:

  • C'è una buona ragione per preferire lo stile più vecchio e più esplicito rispetto a più recente, più conciso?
  • Devo scrivere nuove classi usando il stile conciso, o dovrei provare a far corrispondere il vecchio codice per consistenza? In questo caso è sufficiente la coerenza per giustificare il formato precedente?
posta KChaloux 16.08.2012 - 20:37
fonte

4 risposte

14

Ci sono un paio di casi in cui è ancora richiesto il cosiddetto stile "più vecchio":

A: tipi immutabili che utilizzano l'immutabilità fornita dal linguaggio. Il modificatore readonly in C # blocca quel valore dopo la costruzione. Non c'è modo di imitare questo con le proprietà implementate automaticamente (ancora).

public sealed class FooBarBazInator
{
    private readonly double foo;

    public FooBarBazInator(double foo)
    {
        this.foo = foo;
    }

    public double Foo
    {
        get
        {
            return this.foo;
        }
    }
}

B: I tuoi getter / setter hanno qualsiasi logica di sorta. I codici WPF e Silverlight (e simili) associati ai dati delle classi implementeranno INotifyPropertyChanged in questo modo:

public class FooBarBazInator : INotifyPropertyChanged
{
    private double foo;

    public event PropertyChangedEventHandler PropertyChanged;

    public double Foo
    {
        get
        {
            return this.foo;
        }

        set
        {
            this.foo = value;
            this.RaisePropertyChanged("Foo");
        }
    }

    private void RaisePropertyChanged(string propertyName)
    {
        var propertyChanged = this.PropertyChanged;

        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Oltre a quelli, direi che uso il nuovo stile. Mantiene conciso il codice e offre meno aree di superficie in cui i bug possono insinuarsi. Inoltre, se è necessario modificare la logica, non sarà incompatibile con la firma.

    
risposta data 16.08.2012 - 20:54
fonte
6

Direi che avere un backing field esplicito è semplicemente inutile: rende il tuo codice più lungo e più difficile da leggere. Aggiunge anche il potenziale di errore:

public double Bar
{
    get { return _baz; }
    set { _bar = value; }
}

Penso che un errore come questo potrebbe accadere abbastanza facilmente e sarebbe piuttosto difficile da individuare.

E se vuoi uniformità, fallo in un altro modo: cambia il codice che utilizza i campi di supporto nel codice che utilizza le proprietà automatiche. Questo è particolarmente facile se usi uno strumento di refactoring come ReSharper (e se non usi qualcosa del genere, penso che dovresti iniziare).

Naturalmente, ci sono ancora casi in cui è necessario disporre di backing field, ma penso che non sia rilevante per questa domanda.

    
risposta data 16.08.2012 - 20:54
fonte
1

Anche se la domanda è abbastanza vecchia ho pensato di aggiungere un paio di punti che ho letto da un libro che vale la pena menzionare qui.

  1. I motori di serializzazione in fase di esecuzione mantengono il nome del file in uno stream serializzato. Il nome del campo di supporto per una proprietà implementata automaticamente (AIP) è determinato dal compilatore e potrebbe effettivamente cambiare il nome di questo campo di supporto ogni volta che ricompilate il codice, annullando la possibilità di deserializzare le istanze di qualsiasi tipo che contiene un AIP. Quindi non utilizzare AIP con qualsiasi tipo di serializzazione o deserializzazione.

  2. Quando si esegue il debug, non è possibile inserire un punto di interruzione su un metodo di acquisizione o impostazione AIP, quindi non è possibile rilevare facilmente quando un'applicazione riceve o imposta questa proprietà. È possibile impostare i punti di interruzione sui punti di interruzione implementati manualmente

risposta data 13.05.2015 - 14:13
fonte
-3

Is there a good reason to prefer the older, more explicit style over the newer, more concise one?

Non proprio. Anche se direi che ogni volta che hai passato un passaggio in questo modo, dovresti aver usato un campo pubblico per cominciare.

Should I write any new classes using the concise style, or should I try to match the older code for consistency? Is consistency worth enough in this case to justify the older format?

Supponendo che tu abbia ignorato il consiglio di cui sopra e abbia delle proprietà pass-through, non mirerei a far corrispondere lo stile. Idealmente, torneresti e ridirai il vecchio stile nel nuovo stile per essere coerente, ma la possibilità che le persone leggano male il codice sia snella.

    
risposta data 16.08.2012 - 20:54
fonte

Leggi altre domande sui tag