内部抽象类:如何隐藏程序集外的用法?

时间:2009-08-07 14:14:34

标签: c# inheritance abstract-class access-modifiers

我有一个公共程序集/项目,它有一个抽象基类,然后是几个我想公开给其他程序集的派生类。

我不希望抽象基类出现在Intellisense中的其他程序集中,所以我想我会把它internal,但是我得到了这个错误:

  

可访问性不一致:基类“设置”比类“IrcSettings”更难以访问....

我真的不明白。我被迫制作抽象的Settingspublic,因此在这个集会之外可见。

如何改为创建此课程internal

7 个答案:

答案 0 :(得分:85)

据我所知,您希望您的抽象类只能由同一程序集中的其他类实现(例如,它是内部的),但派生类可以是公共的。

执行此操作的方法是将抽象基类设为public,但为其提供内部默认构造函数:

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

这将允许MyClass(及其成员)对程序集外的类可见并可用,但程序集外的类不能从它继承(将得到编译错误)。

编辑:如果外部程序集可以看到 的类继承自MyClass,则无法阻止MyClass 看到 - 例如,在Intellisense中显示。但是,您可以按照上述步骤阻止使用

答案 1 :(得分:9)

抽象基类必须是公共的,因为类的整个继承层次必须是可见的。这确保了多态性的有效性和有效性;但是所有基类的成员都可以是内部的(包括构造函数),因此不能在程序集外部使用

答案 2 :(得分:6)

你想要实现的目标确实没有多大好处,但你实际想要实现的目标与此类似。

将您的抽象基类放在1个程序集中,内部包含所有内容。在该程序集的AssemblyInfo中,您需要添加

[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]

然后在另一个程序集中,您将拥有您想要公开的所有类。请注意,对于cs_friend_assemblies_2中的任何代码或者您为程序集命名的任何代码,您仍然可以从intellisense访问基类,但不能在其他地方访问。

答案 3 :(得分:4)

您不能同时将该类提供给其他程序集以进行继承,但也可以将其设置为私有,因此其他使用者无法看到该类。您可以将类设置为内部,并使用[InternalsVisibleTo]属性将其公开给特定的程序集(如果它是朋友程序集),但我认为这不是您想要的。

如果你想让代码(派生类除外)不能实例化你的基类,你可以给它一个受保护的构造函数:

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

您可以使用EditorBrowsable属性隐藏Intellisense中的班级成员:

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

应该注意的是,有些人报告IDE的问题并不总是尊重这个属性。

答案 4 :(得分:1)

就我而言,这是一个无问题。观察:

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

如果没有多态性,上述内容将无法工作 - 能够通过其通用接口(抽象基类)引用不同派生类的实例。你想要做的就是把它拿掉并削弱你的类层次结构的可用性。我认为你不应该继续这条道路。

答案 5 :(得分:0)

其他程序集是否会继承自抽象基类或从抽象基类继承的任何公共类?

如果是这样,您必须公开抽象基类。只需制作您不希望在装配体内部可见的方法。

如果没有,也许接口可以帮助?定义公共接口,使您的公共类实现它们,并提供工厂来获取实例。这样,intellisense在程序集之外看到的唯一东西就是接口。

这有帮助吗?

答案 6 :(得分:0)

解决此限制的一种方法是使用合成而不是继承(还有other good reasons来执行此操作)。例如,而不是:

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

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

这样做:

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

如果公众不需要了解IMyBase接口而你的内部也不知道,你可以完全省略require("config.inc.php"); $query = "Select * FROM users WHERE username = :username"; $query_params = array( ':username' => $_POST['username'] ); $stmt = $db->prepare($query); $result = $stmt->execute($query_params); $rows = $stmt->fetchAll(); error--> $estado2 = $rows[0]['estado']; $query = "Select * FROM dogs WHERE adocao = 'Sim' AND estado = $estado2 "; 接口。