Pergunta

Eu tenho um assembly/projeto comum que possui uma classe base abstrata e, em seguida, várias classes derivadas que desejo tornar públicas para outros assemblies.

Não quero que a classe base abstrata apareça nessas outras montagens do Intellisense, então pensei em fazer isso internal, mas recebo este erro:

Acessibilidade inconsistente:a classe base 'Settings' é menos acessível que a classe 'IrcSettings' ....

Eu realmente não entendo isso.Sou forçado a fazer o resumo Settings aula public, e, portanto, visível fora desta montagem.

Como posso fazer essa aula internal em vez de?

Foi útil?

Solução

Pelo que entendi, você deseja que sua classe abstrata seja implementada apenas por outras classes na mesma montagem (por exemplo, é interna), mas as classes derivadas podem ser públicas.

A maneira de fazer isso é tornar a classe base abstrata pública, mas dar um construtor padrão interno:

public abstract class MyClass
{
    internal MyClass() { }
}

Isso permitirá que a MyClass (e, portanto, seus membros) seja visível e utilizável para as aulas fora da sua montagem, mas as aulas fora da sua montagem não podem herdar dela (receberá um erro de compilação).

Editar: se aulas que posso ser visto por montagens externas herdadas da MyClass, você não pode impedir que a MyClass também seja visto - por exemplo, aparecendo no Intellisense. No entanto, você pode impedir que eles sejam usado seguindo o acima.

Outras dicas

A classe base abstrata deve ser pública, pois toda a hierarquia de herança de uma classe deve ser visível.Isso garante que o polimorfismo funcione e seja válido;no entanto, todos os membros das classes base podem ser internos (incluindo o construtor) e, portanto, não utilizáveis ​​fora do seu assembly

Realmente não há muito benefício para o que você está tentando alcançar, mas o que você está realmente procurando alcançar é semelhante a isso.

Tenha sua classe base abstrata em 1 montagem com tudo interno. No AssemblyInfo para essa montagem, você precisa adicionar

[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]

Então, em outra assembléia, você tem todas as aulas que deseja publicamente disponíveis. Observe que você ainda poderá acessar a classe base da IntelliSense para qualquer código dentro de cs_friend_assemblies_2 ou o que você nomeia sua assembléia, mas não em nenhum outro lugar.

Você não pode disponibilizar simultaneamente a classe para outras montagens para herança, mas também privada, para que não possa ser visível para outros consumidores. Você pode tornar a classe interna e expô -la a uma montagem específica (se for uma assembléia de amigos) usando o [InternalsVisibleTo] atributo, mas não acho que seja isso que você deseja.

Se você deseja impedir que o código (exceto as classes derivadas) seja capaz de instanciar sua classe base, você pode fornecer um construtor protegido:

abstract class MyBaseClass
{
    protected MyBaseClass() { ... } // only inheritors can access this...
}

Você pode esconder os membros da classe do intellisense usando o EditorBrowsable atributo:

abstract class MyBaseClass
{ 
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    public void SomeMethodToBeHidden() { }
}

Deve -se notar que algumas pessoas relataram problemas com o IDE nem sempre respeitando esse atributo.

No que me diz respeito, isso é um não problema. Observar:

public abstract class Foo {
    public void virtual Bar() {
        // default implementation
    }
}

public class NormalFoo : Foo { }

public class SpecialFoo : Foo {
    public override void Bar() {
        // special implementation
    }
}

var foolist = new List<Foo>();

foolist.Add( new NormalFoo() );
foolist.Add( new SpecialFoo() );

foreach (var f in foolist) {
    f.Bar();
}

O exposto acima não funcionaria sem polimorfismo - poder se referir a instâncias de diferentes classes derivadas por meio de sua interface comum, a classe base abstrata. O que você quer fazer é tirar isso e prejudicar a usabilidade da sua hierarquia de classe. Eu não acho que você deva continuar por esse caminho.

As outras assembléias herdarão da sua classe base abstrata ou de qualquer uma das classes públicas que herdarão da sua classe base abstrata?

Nesse caso, você deve tornar a classe base abstrata pública. Basta fazer métodos que você não deseja visíveis fora da montagem interna.

Caso contrário, talvez as interfaces possam ajudar? Defina interfaces públicas, faça com que suas aulas públicas as implementem e forneça uma fábrica para obter instâncias. Dessa forma, a única coisa que Intellisense vê fora da assembléia é a interface.

Isso ajuda?

Uma maneira de contornar essa limitação é usar a composição em vez de herança (existem outro boas razões para fazer isso também). Por exemplo, em vez de:

internal abstract class MyBase
{
    public virtual void F() {}
    public void G() {}
}

public class MyClass : MyBase // error; inconsistent accessibility
{
    public override void F() { base.F(); /* ... */ }
}

Fazem isto:

public interface IMyBase
{
    void F();
}

internal sealed class MyBase2 : IMyBase
{
    public void F() {}
    public void G() {}
}

public sealed class MyClass2 : IMyBase
{
    private readonly MyBase2 _decorated = new MyBase2();
    public void F() { _decorated.F(); /* ... */ }
    public void G() { _decorated.G(); }
}

Você pode omitir o IMyBase Interface inteiramente se o público não precisar saber sobre isso e seus internos também não.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top