在C#中是否可以指定仅由同一程序集中存在的类继承的类,而其他程序集的行为应该像公共密封类型。
答案 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)
我知道这是一篇很老的帖子,但我发现另一种方法非常好,我想把它发布给其他人。
````
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#语言本身没有这样的规定。但是,解决方法 - 正如其他人所建议的那样 - 可能就足够了。