仅在C#中的程序集内部可继承

时间:2009-03-10 13:53:48

标签: c# oop inheritance

在C#中是否可以指定仅由同一程序集中存在的类继承的类,而其他程序集的行为应该像公共密封类型。

8 个答案:

答案 0 :(得分:16)

我认为Eric Lippert在这里得到了定义的引用:

答案 1 :(得分:14)

语言本身并没有任何简单易用的东西,但你应该能够通过使你的构造函数内部来做到这一点。但是,如果这样做,您将无法从外部程序集中新建它,因此您必须添加工厂方法。

public class Foo
{
    internal Foo()
    {
    }

    public Foo Create()
    {
        return new Foo();
    }
}

这是一个替代方案,可让您在外部程序集中新建类

public sealed class Foo : FooBase
{

}

public class FooBase
{
    internal FooBase() { }
}

然而,您可能会问自己的一个问题是为什么您希望密封课程。有时这是不可避免的,但我已经看到sealed关键字经常被滥用,以至于我认为我会提起它。通常,开发人员会密封类,因为它们对代码过度保护。 大部分时间,如果一个类设计得很好,就不需要密封。

答案 2 :(得分:5)

如果你的课程是抽象的,那么有一种非常简单的方法:

public abstract class Foo {
    internal abstract void DoNothing();
    // ... other members
}

现在虽然你的班级和大多数成员都是公开的,但内部的抽象成员却无法从汇编之外的类派生出来。

答案 3 :(得分:1)

你不能用语言结构做到这一点,但尝试使用反射

public class MyClass{
  public MyClass(){
    if(this.GetType().Assembly != typeof(MyClass).Assembly){
        throw new Exception("Can't derive from this type!");
  }
}

检查了一下。似乎工作。唯一的问题是,除非有人阅读文档,否则在运行时就会出现问题。

答案 4 :(得分:1)

我能想到的唯一方法是在内部类上使用公共包装器,可能使用通用接口:

public interface IFoo
{
}

internal class Foo : IFoo
{
}

public sealed class PublicFoo : IFoo
{
    private Foo m_Foo = new Foo();
}

答案 5 :(得分:1)

我知道这是一篇很老的帖子,但我发现另一种方法非常好,我想把它发布给其他人。

  1. 使用内部构造函数创建基类。
  2. 使派生类继承自基类并进行密封。
  3. ````

    public abstract class LockResult {
        internal LockResult() {
    
        }
    }
    
    public sealed class LockSucceededResult : LockResult {
        //Info for when a lock succeeded
    }
    
    public sealed class LockFailedResult : LockResult {
        //Info for when a lock failed
    }
    

    ````

答案 6 :(得分:1)

要在10年后回答这个问题(我一直在寻找相同的解决方案,所以我认为如果将来有人遇到相同的问题,写下来很有用),此问题已经得到了解决。 (虽然是间接的),但在C#7.2中引入了“ private protected”访问修饰符。

仅当该修饰符在同一程序集中且从基类派生时,才允许访问。将其应用于构造函数,并且不能在当前程序集之外派生它。顺便说一句,如果您可以摆脱“内部”和/或元数据的影响,那就去做,因为这需要C#7.2,这可能会破坏与旧设备或应用程序的兼容性。还要注意,由此产生的错误(由于保护级别而无法访问构造函数)与您尝试派生密封类(无法派生密封类)时会有所不同,但是最终结果是相同的。

答案 7 :(得分:0)

没有。 C#语言本身没有这样的规定。但是,解决方法 - 正如其他人所建议的那样 - 可能就足够了。