C# imposta la funzione di accesso accessibile a tutti i tipi nell'assembly e ottiene l'assessor solo per i tipi derivati.Come?

StackOverflow https://stackoverflow.com/questions/2081255

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).

È stato utile?

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; }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top