C# Defina o acessador acessível a todos os tipos na montagem e obtenha o avaliador apenas para tipos derivados. Como?
-
21-09-2019 - |
Pergunta
Esta propriedade em um tipo com Sem acesso modificador (assim internal
Acesso):
class SomeType {
private int length;
internal int Length {
get { return length; }
set length = value; }
}
}
permite todos os tipos dentro da montagem de algum tipo de uso get
e set
Acessores. Problema: como restringir o acesso a set
para só Tipos derivados de algum momento (e algum dia)?
internal int Length {
get { return length; }
protected set length = value; }
}
é rejeitado pelo compilador, porque protected
diz -se que é menos restritivo do que internal
(supostamente: protected
tem um interseção com internal
, mas é não está totalmente incluído dentro internal
-> Tipos derivados podem existir além do escopo de internal
).
Qual seria o código ter sido acessado por qualquer tipo dentro da montagem e definido apenas por tipos derivados dentro da montagem?
Editar: Depois de revisar as respostas, acho que preciso adicionar outra característica da propriedade, pois pode fazer a diferença na solução: o tipo de propriedade é realmente SomeType
. O código editado é:
class SomeType {
private SomeType length;
internal SomeType Length {
get { return length; }
set length = value; }
}
}
Se a propriedade for declarada public
, então o compilador emite um erro (o tipo de propriedade é menos acessível ao comprimento da propriedade).
Solução
(Editar: Acabei de verificar, e isso funciona mesmo quando o tipo de propriedade é o mesmo que o tipo de declaração. No entanto, não trabalhar quando você está tentando declarar uma propriedade dentro de um público digite onde o tipo de propriedade é um interno modelo.)
Você não pode fazer isso em C# (estritamente falando), mas pode fazer algo muito semelhante:
protected internal int Length { get; protected set; }
(Isso está usando uma propriedade implementada automaticamente apenas por simplicidade; a mesma técnica também funcionaria para uma propriedade "normal".)
Isso tornará o "getter" acessível a qualquer tipo dentro da mesma montagem e tipos derivados; O "setter" só será acessível aos tipos derivados. Como sua classe é interna de qualquer maneira, isso é praticamente equivalente de qualquer maneira - o getter teoricamente seria acessível a tipos fora da montagem, mas como a classe é interna, nada de uma montagem diferente deve ser derivada do seu tipo de qualquer maneira.
O problema é que as propriedades exigem que um nível de acesso seja um "subconjunto" do outro; internal
e protected
Não funcione assim - um tipo pode estar na mesma montagem, mas não derivado do tipo em questão; Outro tipo pode ser derivado, mas em uma montagem diferente. Eles são ortogonais, basicamente.
A solução acima funciona porque protected internal
significa que é acessível a qualquer tipo que seja qualquer Na mesma montagem ou derivado do tipo. Claramente cada um de protected
e internal
individualmente é um subconjunto disso.
Você gostaria ser capaz de fazer um internal
Propriedade que foi ainda mais restrita para o setter se C# tivesse algum equivalente à "família CLR" e Assembléia "Nível de Acesso. (protected internal
é equivalente a "família ou Assembléia ".) Infelizmente para você, não é :(
Se você verdade Quer os objetivos originalmente declarados (por exemplo, se você mais tarde tiver uma aula pública para a qual deseja aplicar as mesmas restrições), você terá que fazer pelo menos um deles um método separado, por exemplo,
private int length;
internal int Length { get { return length; } }
protected void SetLength(int value)
{
this.length = value;
}
Outras dicas
Já que a classe em si só é visível na assembléia de declaração (devido ao implícito internal
Modificador de acesso), basta fazer o getter na propriedade public
e o setter protected
:
class SomeType {
private int length;
public int Length {
get { return length; }
protected set { length = value; }
}
}
O getter não vou Esteja acessível fora da sua assembléia, pois a aula em si não é visível.
Off Topic: Se você tiver um compilador C# recente, pode querer usar propriedades automáticas:
class SomeType {
public int Length { get; protected set; }
}
Este é apenas um truque de idioma/compilador; portanto, você não precisa compilar uma estrutura da versão 3.x para usá -lo.
Você não pode mudar (não testei):
protected int Length
{
internal get { return length; }
set { length = value; }
}