Pregunta

Tengo una Asamblea común / proyecto que tiene una clase base abstracta, a continuación, varias clases derivadas que quiero hacer público a otros conjuntos.

No quiero la clase base abstracta para aparecer en estas otras asambleas en Intellisense, así que pensé que lo lograría internal, pero me sale este error:

  

inconsistente accesibilidad: la clase base 'Configuración' es menos accesible que 'IrcSettings' clase ....

Realmente no entiendo esto. Me veo obligado a hacer el Settings clase abstracta public, y por lo tanto visible fuera de este montaje.

¿Cómo puedo hacer que esta clase en lugar internal?

¿Fue útil?

Solución

Según tengo entendido, usted quiere que su clase abstracta que se aplicará solamente por otras clases en el mismo conjunto (por ejemplo, que es interno), pero las clases derivadas podría ser pública.

La forma de hacer esto es hacer que la clase base abstracta pública, pero le dan un constructor por defecto interno:

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

Esto permitirá MiClase (y por lo tanto sus miembros) sean visibles y utilizables a clases fuera de su montaje, pero las clases fuera de su montaje no puede heredar de ella (obtendrá un error de compilación).

Editar: Si clases que pueden ser vistos por los montajes externos heredar de MyClass, no se puede evitar que MiClase de ser también ve - por ejemplo, aparecer en Intellisense. Sin embargo, puede evitar que sean utiliza siguiendo el anterior.

Otros consejos

La clase base abstracta tiene que ser público, ya que toda la jerarquía de herencia para una clase tiene que ser visible. Esto asegura que las obras de polimorfismo y es válido; sin embargo todos los miembros de las clases base pueden ser internas (incluyendo el constructor), y por lo tanto no utilizable fuera de su montaje

En realidad no es mucho de un beneficio a lo que estamos tratando de lograr, pero lo que realmente está buscando lograr es similar a esto.

Tenga su clase base abstracta en 1 montaje con todo lo interno. En el AssemblyInfo para que el montaje es necesario agregar

[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]

Luego, en otro montaje que tiene todas las clases que desea a disposición del público. Nota que todavía será capaz de acceder a la clase base de IntelliSense para cualquier código dentro cs_friend_assemblies_2 o lo que el nombre de su ensamblaje, pero no en ninguna otra parte.

No se puede al mismo tiempo hacer que la clase a disposición de otros conjuntos de la herencia, sino también privada para que no pueda ser visible para otros consumidores. Puede hacer que la clase interna, y exponerla a un montaje específico (si se trata de un montaje de amigo) mediante el atributo [InternalsVisibleTo], pero no creo que esto es lo que desea.

Si desea mantener el código (aparte de las clases derivadas) de la posibilidad de crear una instancia de la clase base, que podría darle un constructor protected:

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

Puede ocultar los miembros de la clase de Intellisense usando el atributo EditorBrowsable:

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

Debe tenerse en cuenta que algunas personas han reportado problemas con el IDE no siempre respetando este atributo.

En lo que a mí respecta, este es un problema inexistente. Observe:

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();
}

Lo anterior no funcionaría en absoluto sin polimorfismo - ser capaz de hacer referencia a los casos de diferentes clases derivadas a través de su interfaz común, la clase base abstracta. Lo que se quiere hacer es tomar eso y paralizar la usabilidad de su jerarquía de clases. No creo que se debe seguir por este camino.

¿Los otros conjuntos cada vez heredar de su clase base abstracta o cualquiera de las clases públicas que heredan de la clase base abstracta?

Si es así, usted tiene que hacer pública la clase base abstracta. Simplemente haga métodos no desea visible fuera de la unidad interna.

Si no, tal vez las interfaces pueden ayudar? Definir las interfaces públicas, hacen sus clases públicas ponerlas en práctica, y proporcionar una fábrica para obtener instancias. De esa manera lo único intelisense ve el exterior del conjunto es la interfaz.

¿Le ayuda?

A manera de evitar esta limitación es el uso de la composición en lugar de herencia (hay otro buenas razones para hacer esto también). Por ejemplo, en lugar 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(); /* ... */ }
}

Haga lo siguiente:

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(); }
}

Se puede omitir por completo la interfaz IMyBase si el público no tiene por qué saber sobre él y sus partes internas tampoco.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top