Dovresti creare proprietà private?

19
private string mWhatever;

private string Whatever
{
    get
    {
        return this.mWhatever;
    }
    set
    {
        this.mWhatever = value;
    }
}

Ho visto alcune persone che creano proprietà per ogni singolo membro, privato o meno ... ha senso? Potrei vedere che ha senso nell'1% dei casi, a volte quando si desidera controllare l'accesso al membro all'interno della classe che lo contiene perché se non si utilizzavano le proprietà per ogni membro, si sarebbero verificate incoerenze e si sarebbe verificato se il membro ha un accesso o meno (dal momento che hai accesso ad entrambi nell'ambito della classe).

    
posta fordeka 15.08.2012 - 03:14
fonte

9 risposte

17

Risposta breve: , quando è necessario. Altrimenti, utilizza una Proprietà auto-implementata getter e setter come private string Whatever { get; set;}

  • È molto utile quando utilizzi un approccio del dominio vicino
  • È utile anche quando una logica specifica deve essere controllata quando imposti il valore

Ecco una descrizione completa di quando useresti i setter privati: utilizzo della proprietà C # .

    
risposta data 15.08.2012 - 03:40
fonte
10

Alcune buone risposte già qui, ma penso che la maggior parte di loro manchi un punto della tua domanda:

I've seen some people who make properties for every single member, private or not... does this make any sense?

Penso che sia raramente necessario in anticipo, per ogni singolo membro . Inizia con

 private string Whatever;

Quando in un secondo momento tieni bisogno di incapsulamento o un punto di interruzione condizionale per questo membro specifico, puoi comunque sostituirlo con una proprietà con lo stesso nome - nella maggior parte dei casi senza cambiare il codice che utilizza Whatever . Ma attenzione, ci sono sottili differenze, vedi la risposta di Brian Rasmussen in questo post SO (link fornito anche da Emmad Kareem, +1).

    
risposta data 15.08.2012 - 10:17
fonte
7

Uno dei maggiori vantaggi di questo approccio è il controllo su quando le variabili cambiano .

Considera quanto segue.
Stai eseguendo il debug di un grande progetto. Un certo metodo genera un'eccezione. Si imposta un punto di interruzione e si rivela che una determinata variabile membro ha un valore errato. Supponiamo che il tuo codice si basi su questa variabile in modo molto estensivo e trovi centinaia di usi di scrittura ( Scenario degli spaghetti ). Quindi non puoi capire quale di questi usi ha assegnato un valore errato.
Se il codice è multithread, il debug può diventare un vero incubo.

Con proprietà, puoi impostare un punto di interruzione in un setter . Combinato con una condizione, può essere inchiodato in una sola volta.

VC ++ ha punti di interruzione dei dati , ma è disponibile solo per il codice non gestito.

    
risposta data 15.08.2012 - 04:52
fonte
1

Se non si utilizza una proprietà, l'unica altra opzione è utilizzare un campo per memorizzare i dati variabili. Proprietà e campi hanno differenze significative. La maggior parte di queste differenze si trova Campi vs Proprietà . Ti suggerisco di studiare le differenze e quindi fare la tua scelta in base alle tue esigenze applicative. Tuttavia, tieni presente che l'utilizzo di campi anziché di proprietà non è la pratica OO comune a causa della loro natura e carenza.

    
risposta data 15.08.2012 - 04:39
fonte
1

Le proprietà private possono essere molto utili per incapsulare il comportamento di cose che sono interne alla tua classe. Solo perché sono privati non significa che non dovresti approfittare dello zucchero sintattico che le proprietà ti danno.

L'esempio dato è tuttavia scarso. I getter e gli incastonatori di proprietà dei calderoni come questi sono quasi sempre una cattiva idea. Se utilizzi C # 3.0 o versioni successive, le proprietà auto sono un'idea molto migliore:

private string Whatever { get; set }

Questo è più breve, più pulito e molto più leggibile. In effetti, è appena più lungo della semplice dichiarazione della variabile di supporto.

Ma soprattutto, le proprietà auto possono essere convertite in proprietà complete in qualsiasi momento senza cambiare la semantica del resto del programma! Pertanto, se è necessario aggiungere la convalida o la gestione degli errori, è possibile farlo facilmente.

Così com'è, ho sempre pensato che fosse un peccato che non potessi fare

private readonly string Whatever { get; set }

o

private string Whatever { get; readonly set }

Per applicare solo la possibilità di scrivere sul valore nel costruttore, ma poi I preferisci tipi immutabili .

    
risposta data 15.08.2012 - 16:51
fonte
0

Non è assolutamente necessario farlo per le proprietà private, ma consente di modificare il modo in cui la proprietà ottiene / imposta il valore sottostante senza cambiarne l'accesso.

Ad esempio, modifica del modo in cui è impostato il valore sottostante:

private string Whatever
{
    get
    {
        return this.mWhatever;
    }
    set
    {
        this.mWhatever = string.IsNullOrEmpty(value) ? string.Empty : value;
    }
}
    
risposta data 15.08.2012 - 03:44
fonte
0

Si

Personalmente uso questo come meccanismo di memorizzazione nella cache e potremmo chiamarlo memorizzazione nella cache a livello di proprietà .

private List<User> users;
private List<User> Users
{
    get
    {
        if(users == null) users = new UserManager().GetUsers();
        return users;
    }
}

Ora in altri posti all'interno della mia classe, utilizzo la proprietà Users invece del campo users .

Un'altra possibile situazione potrebbe essere quando si desidera implementare una logica su un campo, ma in modo centralizzato in una classe. Pertanto puoi creare sia un metodo GetFoo() , sia una proprietà Foo per il campo foo .

private string foo;
private string Foo
{
    get
    {
        return "Mr. " + foo;
    }
}
    
risposta data 15.08.2012 - 13:14
fonte
0

Qualcos'altro da considerare:

Le proprietà reali sono dettagli di implementazione. Uno degli obiettivi di OOP è cercare di minimizzare l'esposizione dei dettagli di implementazione laddove possibile.

La ragione è che se si nascondono le proprietà e le si espongono solo attraverso getter e setter, si ha un controllo molto maggiore. Ad esempio, il getter può convalidare il proprio input e impedire che la proprietà venga impostata su uno stato non valido. Se la capacità di modificare il valore è fondamentale per il tempo, anche il setter può proteggersi da questo. Il getter, se il valore reale dovesse essere costoso per qualsiasi motivo, può eseguire l'inizializzazione e / o la memorizzazione nella cache.

Avendo getter e setter esposti e le proprietà nascoste a volte non hai bisogno di alcuna proprietà. Il tuo getter può calcolare il valore su invocazione, o delegare l'attività da qualche altra parte, o qualsiasi cosa che permetta di soddisfare le sue specifiche. Ciò che è importante della tua classe sono le informazioni a cui puoi accedere e non come queste informazioni sono rappresentate internamente.

Naturalmente, se non ci sono conseguenze negative per qualsiasi cosa al di fuori della classe di essere in grado di accedere direttamente a una proprietà, allora dovresti renderla pubblica. Tuttavia, secondo la mia esperienza, questi casi sono relativamente pochi e distanti tra loro.

    
risposta data 15.08.2012 - 13:29
fonte
0

So che questa è una vecchia domanda e tutto @Yusubov ha detto è corretto , ma rispetto al suo secondo punto elenco sulla logica specifica nel setter, e dal momento che non ho visto nessuno menzionarlo espressamente, un esempio perfetto sarebbe quando la classe implementa INotifyPropertyChanged interfaccia.

Questo è usato un sacco in WCF e Silverlight che ti consente di sapere quando una proprietà specifica è cambiata tramite la logica nel suo setter come nella classe qui sotto:

public class Settings : INotifyPropertyChanged
{
    public Settings() 
    { 
        this.CountryField = String.Empty; 
    }

    private string CountryField;
    public string Country
    {
        get { return this.CountryField; }
        set
        {
            if (Object.ReferenceEquals(this.CountryField, value)) { return; }

            this.CountryField = value;
            this.RaisePropertyChanged("Country");
        } 
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler propertyChanged = this.PropertyChanged;

        if (propertyChanged != null)
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
    
risposta data 09.12.2014 - 00:13
fonte

Leggi altre domande sui tag