Non so se la domanda è sufficientemente descrittiva, ma perché e in che modo questo comportamento esiste?
public class Layer { public string Name { get; set; } private IEnumerable children; public IEnumerable Children { get { return this.children.Where ( c => c.Name != null ).Select ( c => c ); } set { this.children = value; } } public Layer ( ) { this.children = new List ( ); // Fine Layer layer = new Layer ( ); layer.children = new List ( ); // Isn't .children private from the outside? } }
Posso accedere a layer.Children
ovunque, va bene, ma come posso accedere a layer.children
dato che è privato?
Layer layer = new Layer ( ); layer.children = new List ( );
funziona solo se il codice si trova all’interno della class Layer
. Esiste un codice speciale per trattare l’accesso alle variabili private in modo diverso se è fatto all’interno della class contenente, anche se l’accesso è dall’esterno?
Conosco il motivo dell’uso:
this.children = ...
all’interno della class contenente, ma creare nuove istanze e modificarle dall’esterno, anche se sono ancora all’interno della class contenente, non sembra una buona pratica.
Qual è la ragione per consentire questo?
Vedere la sezione 3.5.1 delle specifiche del linguaggio C #. Il testo rilevante è questo:
Privato, che viene selezionato includendo un modificatore privato nella dichiarazione membro. Il significato intuitivo di privato è “accesso limitato al tipo di contenuto”.
Si noti che il modificatore è rilevante per il tipo , non per l’ istanza.
E poi ulteriormente nella sezione 3.5.2 alcune regole sono ulteriormente spiegate:
In termini intuitivi, quando si accede a un tipo oa un membro M, vengono valutati i seguenti passaggi per garantire che l’accesso sia consentito:
- Innanzitutto, se M è dichiarato all’interno di un tipo (al contrario di un’unità di compilazione o di un namespace), si verifica un errore in fase di compilazione se tale tipo non è accessibile.
- Quindi, se M è pubblico, l’accesso è consentito.
- Altrimenti, se M è protetto internamente, l’accesso è consentito se si verifica all’interno del programma in cui M è dichiarato, o se si verifica all’interno di una class derivata dalla class in cui M è dichiarato e avviene attraverso il tipo di class derivata (§ 3.5.3).
- Altrimenti, se M è protetto, l’accesso è consentito se si verifica all’interno della class in cui è dichiarato M, o se si verifica all’interno di una class derivata dalla class in cui è dichiarato M e avviene attraverso il tipo di class derivata (§3.5 .3).
- Altrimenti, se M è interno, l’accesso è consentito se si verifica all’interno del programma in cui M è dichiarato.
- Altrimenti, se M è privato, l’accesso è consentito se si verifica all’interno del tipo in cui è dichiarata M.
- In caso contrario, il tipo o il membro non è accessibile e si verifica un errore in fase di compilazione.
Questo è un design comune. Si presume che chiunque abbia scritto la class sappia come lavorarci correttamente e capisca cosa significa accedere direttamente ai membri privati. Pertanto, l’accesso ai membri privati di altre istanze della stessa class spesso funziona. Se hai familiarità con il costrutto friend
C ++, allora è come se le istanze della stessa class fossero tutte amiche tra loro (anche se C # non ha alcuna nozione di friend
ufficialmente).
Funziona in C # e Java, quelle sono le due lingue che conosco in cima alla mia testa. Scommetto che molte altre lingue permettono anche a questo (qualcuno vuole entrare?)
Ricorda, il modificatore di accesso privato dice che i Private members are accessible only within the body of the class or the struct in which they are declared
. Questa descrizione è confusa ma dice chiaramente che la restrizione è a livello di class e NOT OBJECT LEVEL
. In questo caso, il livello è ancora all’interno della class.
Questo è stato discusso qui prima. possiamo accedere a una variabile privata usando un object