C# 仅在C中的程序集内部可继承#
在C语言中,是否有方法指定一个类仅由同一程序集中的类继承,对于其他程序集,该类的行为应类似于公共密封类型。否。C语言本身没有此类规定。但是,解决方法——正如其他人在这里建议的那样——可能已经足够了。语言本身没有任何东西可以让这变得容易,但是您应该能够通过使构造函数内部化来做到这一点。但是,如果您这样做,您将无法从外部程序集更新它,因此您必须添加一个工厂方法C# 仅在C中的程序集内部可继承#,c#,oop,inheritance,C#,Oop,Inheritance,在C语言中,是否有方法指定一个类仅由同一程序集中的类继承,对于其他程序集,该类的行为应类似于公共密封类型。否。C语言本身没有此类规定。但是,解决方法——正如其他人在这里建议的那样——可能已经足够了。语言本身没有任何东西可以让这变得容易,但是您应该能够通过使构造函数内部化来做到这一点。但是,如果您这样做,您将无法从外部程序集更新它,因此您必须添加一个工厂方法 public class Foo { internal Foo() { } public Foo Crea
public class Foo
{
internal Foo()
{
}
public Foo Create()
{
return new Foo();
}
}
这里有一个替代方法,可以让您在外部程序集中新建类
public sealed class Foo : FooBase
{
}
public class FooBase
{
internal FooBase() { }
}
然而,您可能会问自己一个问题,那就是为什么要密封该类。有时这是不可避免的,但我经常看到
sealed
关键字被滥用,我想我应该提起它。通常,开发人员会密封类,因为它们过度保护代码。大多数情况下,如果一个类设计得很好,它就不需要被密封。如果你的类是抽象的,有一个非常简单的方法可以做到:
public abstract class Foo {
internal abstract void DoNothing();
// ... other members
}
现在,尽管您的类和大多数成员都是公共的,但内部抽象成员使您无法从程序集外部的类派生。语言构造无法做到这一点,但请尝试使用反射
public class MyClass{
public MyClass(){
if(this.GetType().Assembly != typeof(MyClass).Assembly){
throw new Exception("Can't derive from this type!");
}
}
检查过了。看起来很有效。唯一的问题是,除非有人阅读文档,否则在运行时就会知道问题所在。我能想到的唯一方法是在内部类上使用公共包装器,可能有一个公共接口:
public interface IFoo
{
}
internal class Foo : IFoo
{
}
public sealed class PublicFoo : IFoo
{
private Foo m_Foo = new Foo();
}
我认为Eric Lippert在这里得到了定义性的引用:
- 使用内部构造函数生成基类
- 使派生类从基类继承并密封 ````
- 我知道这是一篇老文章,但我找到了另一种非常有效的方法,我想为其他人发布它
````10年后,为了回答这个问题(我一直在寻找相同的解决方案,所以我想写下它会很有用,以防将来其他人也会遇到同样的问题),这个问题已经在C#7.2中引入了“访问修饰符”,并在本地(尽管是间接)解决了
仅当此修饰符位于同一程序集中且派生自基类时,此修饰符才允许访问。将其应用于构造函数,并且它不能在当前程序集之外派生。另一方面,如果你能摆脱“内部”和/或元数据的困扰,那就去做吧,因为这需要C#7.2,这可能会破坏与旧设备或应用程序的兼容性。还请注意,由此产生的错误(由于保护级别而无法访问构造函数)与您尝试派生密封类(无法派生密封类)时得到的错误不同,但最终结果是相同的。这在技术上是正确的,但我怀疑Ramesh可能已经直觉地知道了这一点。提供潜在的解决方法更有帮助。如果你能像处理过时的代码一样,用某种属性来标记它,那就太好了。你可以在注释中添加:“这个类不能被继承。”+1-供你参考。但问题是我需要它用于ConfigurationElementCollection,所以,我不认为构造函数不能在我的案例中设置为内部构造函数尝试第二种解决方案,创建一个具有内部构造函数的基类,然后用一个具有公共构造函数的密封类实现它。我建议将方法命名为
PreventExternalInheritance
或类似的东西。@Michael answer()提供了相同的解决方案
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
}