50

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

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

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

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

我怎样才能做这门课internal呢?

4

7 回答 7

98

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

这样做的方法是将抽象基类公开,但给它一个内部默认构造函数:

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

这将允许 MyClass(以及它的成员)对程序集之外的类可见和可用,但程序集之外的类不能从它继承(会出现编译错误)。

编辑:如果外部程序集可以看到的类MyClass 继承,则不能阻止 MyClass 也被看到- 例如,出现在 Intellisense 中。但是,您可以按照上述方法阻止它们被使用。

于 2009-08-07T14:16:56.380 回答
10

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

于 2009-08-07T14:16:12.823 回答
8

你想要达到的目标并没有太大的好处,但你真正想要达到的目标与此类似。

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

[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]

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

于 2009-08-07T14:19:51.977 回答
5

您不能同时使该类可用于其他程序集以进行继承,但也不能使其私有,因此其他使用者无法看到它。您可以将类设为内部,并使用该属性将其公开给特定程序集(如果它是朋友程序集)[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 并不总是尊重此属性的问题。

于 2009-08-07T14:21:08.713 回答
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();
}

如果没有多态性,上述内容根本无法工作——能够通过它们的公共接口、抽象基类来引用不同派生类的实例。你想要做的就是把它拿走并削弱你的类层次结构的可用性。我认为你不应该继续走这条路。

于 2009-08-07T17:48:28.040 回答
0

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

如果是这样,您必须公开抽象基类。只需使您不希望在程序集内部可见的方法即可。

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

这有帮助吗?

于 2009-08-07T14:32:07.230 回答
0

解决此限制的一种方法是使用组合而不是继承(也有其他 很好的理由这样做)。例如,而不是:

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如果公众不需要知道它并且您的内部人员也不需要,您可以完全省略该接口。

于 2015-11-17T16:45:38.717 回答