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

m3n*_*tat 48 c# inheritance abstract-class access-modifiers

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

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

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

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

我怎样才能成为这门课internal呢?

Rex*_*x M 89

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

这样做的方法是将抽象基类设为public,但为其提供一个内部默认构造函数:

public abstract class MyClass
{
    internal MyClass() { }
}
Run Code Online (Sandbox Code Playgroud)

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

编辑:如果这班可以通过外部组件可看出从MyClass的继承,你不能阻止MyClass的距离也被看作 -例如,显示智能感知的.但是,您可以按照上述方法阻止它们被使用.

  • 我的问题不是关于错误.我已经阻止了这一点.它不会使用在程序集外部无法使用的Class来污染Intellisense. (3认同)
  • 你_不能_使基类比派生类更难访问。您_可以_使基类成员(而不是类本身)成为内部成员。 (2认同)

the*_*oop 9

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

  • 除非我弄错了,否则这与多态性无关:类可以实现内部接口,并且将该接口转换为抽象类不会改变方法的继承方式等。理论上,我们可以完美地定义一个具有内部基类的类,并在其他程序集中使用它。只是 C#(或 .NET?)不允许这样做。 (3认同)

Chr*_*sic 6

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

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

[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]
Run Code Online (Sandbox Code Playgroud)

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

  • 我认为这是OP真正实现他想要的目标的唯一建议,虽然这是一个非常糟糕的方法,但仍然+1 (2认同)
  • 我可能找不到OP想要实现的目标的价值,但我不会说这是一个糟糕的方法。这基本上打开了.NET 中的“友元程序集”。在错误的情况下使用友元程序集可能会导致糟糕的代码和糟糕的框架,但这可能来自于不良实践。我发现友元程序集最需要的用途是用于测试项目,有时在 ServiceLayer 依赖项中(例如 UpdatedBy 是 { public get; inside protected set } 并且允许服务分配 UpdatedBy 但没有其他地方)。 (2认同)

LBu*_*kin 5

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

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

abstract class MyBaseClass
{
    protected MyBaseClass() { ... } // only inheritors can access this...
}
Run Code Online (Sandbox Code Playgroud)

您可以使用以下EditorBrowsable属性在 Intellisense 中隐藏类成员:

abstract class MyBaseClass
{ 
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    public void SomeMethodToBeHidden() { }
}
Run Code Online (Sandbox Code Playgroud)

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

  • @LBushkin,这很好,但是在抽象类上拥有受保护的默认构造函数实际上并没有做任何事情 - 该类已经无法实例化,因为它是抽象的,并且构造函数的可访问性已经被限制为派生类。 (3认同)
  • EditorBrowsableAttribute 仅对类成员有效,对类声明无效。 (2认同)