Perché e in che modo C # consente l’accesso a variabili private al di fuori della class stessa quando si trova all’interno della stessa class contenitore?

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