2009-11-09 4 views
5

In Visual Studio 2008 Team System, ho appena eseguito Analisi codice (dal menu Analizza) in uno dei miei progetti C#. Una delle avvertenze prodotte è stata la seguente:C# campo protetto a privato, aggiungere proprietà - perché?

Microsoft.Design: Perché campo 'Connection._domain' è visibile al di fuori del suo tipo dichiarando, cambiare la sua accessibilità a privati ​​e aggiungere una proprietà, con la stessa accessibilità come la campo ha attualmente, per fornire l'accesso ad esso.

E 'riferendosi al seguente campo:

public abstract class Connection 
{ 
    protected string _domain; 
} 

Non capisco il ragionamento dietro il suggerimento. Questo è ciò che penso che vuole che io faccia:

public abstract class Connection 
{ 
    private string _domain; 
    protected string Domain { get { return _domain; } set { _domain = value; } } 
} 

Due domande:

  1. Ho capito bene che cosa il suggerimento vuole che io faccia, il codice-saggio?
  2. Perché mi vuole fare questo?
+0

Vedere anche http://stackoverflow.com/questions/1410645/are-public-fields-ever-ok, http://stackoverflow.com/questions/480627/why-wont-anyone-accept-public-fields -in-c, http://stackoverflow.com/questions/1277572/should-i-use-public-properties-and-private-fields-or-public-fields-for-data e molti altri (cercare 'pubblica campi). Tutti discutono i campi pubblici ma generalmente si applicano anche ai campi protetti. –

risposta

13

Sì, credo di aver capito correttamente - anche se in versioni successive di C#, c'è un modo più conciso di scriverlo:

public string Domain { get; set; } 

Perché? Si tratta di incapsulamento. Se si fa come suggerisce, è possibile modificare in seguito la definizione della proprietà Dominio senza influire su alcun codice di chiamata che utilizza tale proprietà. Dal momento che la tua classe è pubblica e potrebbe essere chiamata per codice che non hai scritto, è potenzialmente abbastanza importante.

+0

nel suo caso, 'stringa protetta Domain {get; impostato; } ' – nawfal

2

Sì. Questo è il suggerimento. Non dovresti avere accessibilità superiore a quella privata esposta come campi di istanze dirette.

È uno dei principi principali di OOD - l'incapsulamento indicato anche come "nascondiglio dei dati".

2
  1. Sì, hai corretto il codice problema.
  2. Riguarda l'incapsulamento. _domain sono dati sul tuo oggetto. Piuttosto esponendolo direttamente in modo che ogni client abbia accesso non filtrato, è necessario fornire un'interfaccia per accedervi. In pratica, questo potrebbe aggiungere la convalida al setter in modo che non possa essere impostato su alcun valore. Potrebbe sembrare sciocco se tu sei l'unico codice di scrittura perché sai come funziona la tua API. Ma prova a pensare a cose a livello aziendale di grandi dimensioni, è meglio avere un'API in modo che il tuo oggetto possa essere visto come una scatola che accompagna un compito. Potresti dire che non avrai mai bisogno di aggiungere qualcosa come la validazione a quell'oggetto, ma le cose sono fatte in quel modo per tenerne conto e anche per essere coerenti.
2

Questo perché se si desidera modificare il campo in una proprietà in futuro si interromperà qualsiasi altro assembly che dipende da esso.

È buona prassi mantenere tutti i campi privati ​​e avvolgerli nelle proprietà in modo da avere la possibilità di aggiungere la convalida o altra logica in futuro senza ricompilare tutti gli utenti (o in questo caso gli eredi) della classe.

+0

Perché il downvote? Tecnicamente questo è vero. L'IL per accedere a un campo è diverso da quando si accede a un campo. Se si compila un assembly (A), che fa riferimento a campi in un assembly diverso (B), quindi aggiornare il gruppo (B) e cambiare i campi di proprietà, il montaggio (A) sarà rotto. – Bob

+0

Sono d'accordo, Bob, credo che questa è una considerazione molto importante. (1) Modifica di un campo a una proprietà (perché si vuole aggiungere la logica di convalida o la registrazione o vuole rendere virtuale, o qualunque altra ragione ci potrebbe essere) è un cambiamento di rottura binario a tutti gli utenti della classe. È anche probabile che si verifichi un'interruzione del livello di origine se si nominano i campi in minuscolo e le proprietà in maiuscolo, come la convenzione. – Joren

+0

E questa è la ragione per cui dovresti usare le proprietà. Se così non fosse, non ci sarebbe motivo di usare le proprietà fino a quando non avrai deciso di averne bisogno. Pensavo che rispondesse alla domanda/scrollando le spalle :) – GraemeF

2

La tua traduzione è corretta.Lo stesso argomento per può essere fatto per utilizzare le proprietà 'protette', come può essere fatto per utilizzare le proprietà 'pubblici', invece di esporre direttamente le variabili membro.

Se questo porta solo a una proliferazione di semplici getter e setter, allora penso che il danno alla readablità del codice superi il vantaggio di poter cambiare il codice in futuro. Con lo sviluppo di proprietà generati dal compilatore in C# questo non è poi così male, basta usare:

protected string Domain { get; set; } 
0

In risposta alla tua domanda ... sì.

Tuttavia, vorrei solo usare la sintassi auto-immobile:

public abstract class Connection 
{ 
    protected string Domain { get; set; } 
} 
0

In sostanza, le proprietà forniscono più di ritorno o l'impostazione di un membro. Essi consentono di aggiungere una logica che potrebbe verificare un formato di input, una convalida dell'intervallo, ecc.

La risposta selezionata dal collegamento la mette meglio, "Le proprietà forniscono l'incapsulamento.È possibile racchiudere qualsiasi convalida/formulazione/conversione necessaria nel codice per la proprietà, sarebbe difficile da fare per i campi ".

http://social.msdn.microsoft.com/Forums/en-IE/netfxbcl/thread/985f4887-92ae-4ec2-b7ae-ec8cc6eb3a42

0

In aggiunta alle altre risposte qui menzionati,/membri pubblici protetti che iniziano con un carattere di sottolineatura non sono CLS-compliant, nel senso che non v'è alcun obbligo per linguaggi .NET per sostenere i membri con importanti sottolineature, in modo da qualcuno l'ereditarietà della tua classe in una diversa lingua .NET potrebbe non essere in grado di accedere a quel particolare membro protetto.

lo so, probabilmente non si applica a voi, ma potrebbe essere una delle ragioni per l'avvertimento analisi del codice.