2010-01-28 10 views
11

Questo è qualcosa con cui ho sempre lottato nel mio codice. Supponiamo di avere il seguente codice:Quando all'interno di una classe, è meglio chiamare i suoi membri privati ​​o le sue proprietà pubbliche?

public class MyClass { 
    private string _myVariable; 

    public string MyVariable { 
     get { return _myVariable; } 
     set { _myVariable = value; } 
    } 

    public void MyMethod() { 
     string usingPrivateMember = _myVariable; // method A 
     string usingPublicProperty = MyVariable; // method B 
    } 
} 

Quale modo è più corretto - metodo A o B? Sono sempre tormentato da questo. Il metodo A sembra essere molto più veloce, perché non deve accedere a una proprietà prima di ottenere la variabile reale. Tuttavia, il metodo B è più sicuro perché se il getter di MyVariable aggiunge la logica aziendale, si è sicuri chiamandolo sempre, anche se non esiste una logica aziendale corrente.

Qual è il consenso generale?

+0

e di http://stackoverflow.com/questions/1545297/fields-vs-properties-for-private-class-variables –

+1

Grazie per aver trovato quelli! Ho provato a cercare ma credo di non aver cercato usando parole chiave corrette. – Amberite

+1

la ricerca SO è * ancora * molto scarsa, hai provato Google e "site: stackoverflow.com"? – Ash

risposta

12

Utilizzare la proprietà.

Penso che la proprietà dovrebbe essere interamente responsabile della gestione di quel campo.

Ci sono molte implementazioni in cui non importa, ma ci sono molti punti in cui è importante - molto. Inoltre, questo può essere un po 'difficile da rintracciare, perché è sempre look giusto.

Si andrà errato chiamando la proprietà molto meno volte rispetto a chiamare il campo e laddove esistono le eccezioni a questa regola, documentare la motivazione.

+0

Un vantaggio dell'utilizzo della proprietà è che è possibile impostare un punto di interruzione su ogni lettura/scrittura. Questo è particolarmente utile su basi di codice grandi e poco familiari. Ti permette di scavalcare grossi pezzi di codice nel debugger, ma si fermano comunque quando la proprietà viene modificata. Molto maneggevole. –

+0

Può anche essere utile durante il test dell'unità con stub, poiché è possibile impostare un valore sulla proprietà di stub, ma non su un membro privato. – Jay

1

Questo dipenderebbe davvero da cosa si sta accedendo alla proprietà. Considerare i seguenti due scenari:

Scenario 1: si scrive un metodo per fornire un'azione comune sui dati della classe:

// assume a hypothetical class Position 

public class Circle 
{ 
    private int _radius; 
    private int _xpos; 
    private int _ypos; 

    public int Radius { get { return _radius; } } 
    public Position Center { get { return new Position(_xpos, _ypos); } } 

    public bool PointInCircle(Position other) 
    { 
     return distance(this.Center, other) < this.Radius; 
    } 
} 

chiaramente il comportamento PointInCircle dovrebbe essere lo stesso come se l'utente esegue il codice al suo interno. Pertanto, ha senso utilizzare le proprietà pubbliche.

Scenario 2: si scrive un metodo per manipolare i dati sottostanti. Un buon esempio di questo è la serializzazione. Si desidera serializzare i membri dati sottostanti in contrapposizione ai valori restituiti dai metodi di accesso alle proprietà.

1

dipende, se si accede alla proprietà, potrebbe esserci un codice di 'validazione' che viene chiamato.

private int timeSinceLastPropertyAccess; 

public int TimeSinceLastPropertyAccess 
{ 
    get 
    { 
     // Reset timeSinceLastPropertyAccess to 0 
     int a = timeSinceLastPropertyAccess; 
     timeSinceLastPropertyAccess = 0; 
     return a; 
    } 
} 

Vuoi timeSinceLastPropertyAccess ad essere resettato quando viene utilizzato quando all'interno della vostra classe o no?

+0

Questo è un pessimo design getter. Ottenere metodi non dovrebbe modificare lo stato. –

+0

Troppo vero, ma mostra che i getter possono avere effetti indesiderati se usati. – PostMan

+2

Considera che stiamo parlando di essere all'interno della stessa classe che ha queste proprietà. Quindi, se i getter sono abbastanza spregevoli da avere effetti collaterali importanti è interamente una tua scelta. –

1

Solo per aggiungere un'altra cosa, il tuo esempio ha solo chiesto informazioni sui getter. L'altra metà di questo è setter.

A volte si desidera che l'oggetto utilizzi i setter e talvolta si vorrebbe che ignori e assegni semplicemente il campo sottostante.

Ad esempio, supponiamo di avere una proprietà denominata IsModified. Che direbbe ogni volta che l'oggetto è stato modificato. Potresti fare in modo che tutti i setter inversino a true nel caso in cui venga assegnato un valore diverso a uno dei campi sottostanti.

Ora se si sta idratando quell'oggetto (caricando da un db o da qualche altra parte) allora non si vorrebbe impostare IsModified. Perché, francamente, non è ancora stato modificato. Quindi in quel metodo usi i nomi di campo sottostanti, ma in tutti gli altri metodi usi il setter di proprietà.

0

dipende, vuoi fare ciò che fa la proprietà? privato/pubblico non importa, è come chiamare una funzione.

così com'è, hai appena creato una "funzione" in attesa di dover fare qualcosa ogni volta che si accede o si modifica quel valore.

il problema con il fare questo è si potrebbe venire a trovare si vuole fare una cosa in cui il suo accesso in alcuni punti, e un altro quando il suo accesso in altri luoghi, in modo si sta ancora andando ad avere per cambiare tutte le 'chiamate 'ad esso in uno dei posti.

il fatto è che, se TUTTO quello che accede a quella variabile - anche la classe privata funziona - lo fa attraverso la proprietà che passa semplicemente attraverso la variabile, perché preoccuparsi di avere la proprietà del tutto? perché non creare semplicemente la variabile chiamata "MyVariable", quindi se trovi che vuoi fare qualcosa quando viene modificata/acceduta, basta creare un'altra variabile chiamata _MyVariable o qualcosa, quindi cambiare MyVariable in modo che sia una proprietà per _MyVariable.

dovresti pensare alle proprietà come alle funzioni accessor() e mutator() che hai usato per scrivere, il trucco con loro è stato, se hai trovato che DID vuoi fare del codice ogni volta che si accede a una variabile 'dovevi cambiare TUTTE le chiamate a quella variabile per usare invece un accessor (chiamando una funzione, piuttosto che accedere semplicemente a una variabile membro), ecco perché dovresti creare accessors e matadors' default ', per ogni evenienza. Come ho detto sopra, non hai questo problema con C# e proprietà (eccetto in un caso di lame in cui non puoi scrivere ai membri secondari di un membro se è una proprietà ... PERCHÉ ??)

Problemi correlati