C# imposta la funzione di accesso accessibile a tutti i tipi nell'assembly e ottiene l'assessor solo per i tipi derivati.Come?
-
21-09-2019 - |
Domanda
Questa proprietà in un tipo con nessun accesso modificatore (quindi internal
accesso):
class SomeType {
private int length;
internal int Length {
get { return length; }
set length = value; }
}
}
consente l'utilizzo di tutti i tipi all'interno dell'assembly di SomeType get
E set
accessori. Problema:come limitare l'accesso a set
A soltanto tipi derivati da SomeType (e SomeType in effetti)?
internal int Length {
get { return length; }
protected set length = value; }
}
viene rifiutato dal compilatore, perché protected
si dice che sia meno restrittivo di internal
(presumibilmente: protected
ha un intersezione con internal
, ma è non del tutto compreso In internal
--> I tipi derivati possono esistere oltre l'ambito di internal
).
Quale sarebbe il codice avere accesso da qualsiasi tipo all'interno dell'assembly e impostato solo da tipi derivati all'interno dell'assembly?
Modificare:dopo aver esaminato le risposte, credo di dover aggiungere un'altra caratteristica dell'immobile, poiché potrebbe fare la differenza nella soluzione:il tipo di proprietà è in realtà SomeType
.Il codice modificato è:
class SomeType {
private SomeType length;
internal SomeType Length {
get { return length; }
set length = value; }
}
}
Se la proprietà è dichiarata public
, il compilatore genera un errore (il tipo di proprietà SomeType è meno accessibile della proprietà Length).
Soluzione
(MODIFICARE:Ho appena controllato e funziona anche quando il tipo della proprietà è lo stesso del tipo dichiarante.Tuttavia, esso no funziona quando stai tentando di dichiarare una proprietà all'interno di a pubblico type dove il tipo della proprietà è an interno tipo.)
Non puoi farlo in C# (in senso stretto), ma puoi fare qualcosa di molto simile:
protected internal int Length { get; protected set; }
(Si utilizza una proprietà implementata automaticamente solo per semplicità;la stessa tecnica funzionerebbe anche per una proprietà "normale".)
Ciò renderà il "getter" accessibile a qualsiasi tipo all'interno dello stesso assembly E tipi derivati;il "setter" sarà accessibile solo ai tipi derivati.Dato che la tua classe è comunque interna, questo è comunque praticamente equivalente: il getter sarebbe teoricamente accessibile ai tipi esterni all'assembly, ma poiché la classe è interna, nulla da un assembly diverso dovrebbe comunque derivare dal tuo tipo.
Il problema è che le proprietà richiedono che un livello di accesso sia un "sottoinsieme" dell'altro; internal
E protected
non funziona così: un tipo può trovarsi nello stesso assembly ma non derivare dal tipo in questione;da esso è possibile derivare un altro tipo ma in un assieme diverso.Fondamentalmente sono ortogonali.
La soluzione di cui sopra funziona perché protected internal
significa che è accessibile a qualsiasi tipo che sia O nella stessa assemblea O derivato dal tipo.Chiaramente ciascuno di protected
E internal
individualmente è un sottoinsieme di questo.
Voi volevo essere in grado di fare un internal
proprietà che veniva ulteriormente limitata per il setter se C# avesse avuto un equivalente alla famiglia "CLR". E livello di accesso "assemblaggio".(protected internal
equivale a "famiglia". O assembly".) Sfortunatamente per te, non è così :(
Se tu Veramente desiderare gli obiettivi originariamente dichiarati (ad es.se in seguito disponi di una classe pubblica a cui desideri applicare le stesse restrizioni), dovrai invece rendere almeno una di esse un metodo separato, ad es.
private int length;
internal int Length { get { return length; } }
protected void SetLength(int value)
{
this.length = value;
}
Altri suggerimenti
Poiché la classe stessa è visibile solo nell'assembly dichiarante (a causa dell'implicit internal
modificatore di accesso), basta creare il getter sulla proprietà public
e il palleggiatore protected
:
class SomeType {
private int length;
public int Length {
get { return length; }
protected set { length = value; }
}
}
Il raccoglitore non lo farà essere accessibile al di fuori dell'assembly, poiché la classe stessa non è visibile.
Fuori tema:se hai un compilatore C# recente, potresti invece voler utilizzare le proprietà automatiche:
class SomeType {
public int Length { get; protected set; }
}
Questo è solo un trucco del linguaggio/compilatore, quindi non è necessario compilare con un framework versione 3.X per utilizzarlo.
Non puoi girarlo (non l'ho testato):
protected int Length
{
internal get { return length; }
set { length = value; }
}