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

发布于 2024-07-30 05:44:25 字数 342 浏览 4 评论 0原文

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

我不希望抽象基类出现在 Intellisense 中的其他程序集中,因此我想将其设置为内部,但我收到此错误:

可访问性不一致:基类“Settings”的可访问性低于类“IrcSettings”......

我真的不明白这一点。 我被迫将抽象 Settings 类设置为 public,从而在该程序集之外可见。

我怎样才能让这个类成为内部呢?

I have a common assembly/project that has an abstract base class, then several derived classes that I want to make public to other assemblies.

I don't want the abstract base class to show up in these other assemblies in Intellisense, so I thought I'd make it internal, but I get this error:

Inconsistent accessibility: base class 'Settings' is less accessible than class 'IrcSettings' ....

I don't really get this. I am forced to make the abstract Settings class public, and thus visible outside this assembly.

How can I make this class internal instead?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

情绪少女 2024-08-06 05:44:26

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

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

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

这有帮助吗?

Will the other assemblies ever inherit from your abstract base class or any of the public classes that do inherit from your abstract base class?

If so, you have to make the abstract base class public. Just make methods you don't want visible outside the assembly internal.

If not, maybe interfaces can help? Define public interfaces, make your public classes implement them, and provide a factory to get instances. That way the only thing intellisense sees outside the assembly is the interface.

Does that help?

浸婚纱 2024-08-06 05:44:26

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

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

A way to work around this limitation is to use composition instead of inheritance (there are other good reasons to do this too). For example, instead of:

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

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

Do this:

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

You can omit the IMyBase interface entirely if the public doesn't need to know about it and your internals don't either.

哆兒滾 2024-08-06 05:44:25

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

实现此目的的方法是将抽象基类设为公共,但为其提供一个内部默认构造函数:

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

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

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

As I understand, you want your abstract class to only be implemented by other classes in the same assembly (e.g. it is internal) but the derived classes could be public.

The way to do this is to make the abstract base class public, but give it an internal default constructor:

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

This will allow MyClass (and hence its members) to be visible and usable to classes outside your assembly, but classes outside your assembly cannot inherit from it (will get a compile error).

Edit: If classes which can be seen by external assemblies inherit from MyClass, you cannot prevent MyClass from also being seen - e.g., showing up in Intellisense. However, you can prevent them from being used by following the above.

只涨不跌 2024-08-06 05:44:25

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

The abstract base class has to be public, as the entire inheritance heirarchy for a class has to be visible. This ensures the polymorphism works and is valid; however all the base classes' members can be internal (including the constructor), and hence not usable outside your assembly

人事已非 2024-08-06 05:44:25

对于您想要实现的目标来说确实没有太大好处,但您实际上想要实现的目标与此类似。

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

[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]

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

There really isn't much of a benefit to what you're trying to achieve but what you're actually looking to achieve is similar to this.

Have your abstract base class in 1 assembly with everything internal. In the AssemblyInfo for that assembly you need to add

[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]

Then in another assembly you have all the classes you want publicly available. Note you will still be able to access the base class from intellisense for any code inside cs_friend_assemblies_2 or whatever you name your assembly but not any where else.

许你一世情深 2024-08-06 05:44:25

您不能同时使该类可用于其他程序集的继承,同时又使其成为私有的,因此其他使用者无法看到该类。 您可以将类设为内部类,并使用 [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 不总是尊重此属性的问题。

You can't simultaneously make the class available to other assemblies for inheritance but also private so it can't be visible to other consumers. You can make the class internal, and expose it to a specific assembly (if it's a friend assembly) using the [InternalsVisibleTo] attribute, but I don't think this is what you want.

If you want to keep code (other than derived classes) from being able to instantiate your base class, you could give it a protected constructor:

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

You can hide the class members from Intellisense using the EditorBrowsable attribute:

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

It should be noted that some people have reported problems with the IDE not always respecting this attribute.

清晨说晚安 2024-08-06 05:44:25

就我而言,这不是问题。 观察:

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

如果没有多态性,上面的方法根本不起作用——能够通过公共接口(抽象基类)引用不同派生类的实例。 你想要做的就是去掉它并削弱类层次结构的可用性。 我认为你不应该继续走这条路。

As far as I'm concerned, this is a non-problem. 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();
}

The above wouldn't work at all without polymorphism -- being able to refer to instances of different derived classes through their common interface, the abstract base class. What you want to do is take that away and cripple the usability of your class hierarchy. I don't think you should continue down this path.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文