C# Defina o acessador acessível a todos os tipos na montagem e obtenha o avaliador apenas para tipos derivados. Como?

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

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

Foi útil?

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; }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top