抽象类在c#中不能被密封吗?

6

我在某个地方读到:

"抽象和封闭修饰符等同于一个静态类"

我还发现:

"当您声明一个静态类时,编译器在内部将该类标记为抽象和封闭,并在IL代码中创建一个私有构造函数"

因此,我决定这样做:

static class A
{
    public static void test()
    {
        Console.WriteLine("test");
    }
}

现在,"A"类不能被继承或实例化。
因此,让我们编写一个使用"抽象"来防止实例化并使用"密封"来防止继承的"B类"。
但是,这种方法失败了。
应该等同于:
public abstract sealed class B
{
    private B()
    {

    }
    public void test()
    {
        Console.WriteLine("test");
    }
}

但是我收到了一个错误,显示“错误 CS0418: B':抽象类不能被封闭或静态”。 有什么想法为什么这是不可能的?

感谢您提前的答复。


3
为什么你想要抽象密封类?这毫无意义。 - Kamil Budziewski
7
编译器所做的并不一定被开发者遵循。 - Alireza
5
编译器不允许你使用"abstract sealed class"这样的语法,尽管这与"static class"的作用是相同的。编译器期望你使用"static class"来实现这个功能。 - Tim S.
@nowhewhomustnotbenamed。不,你不能在C#中同时使用abstractsealed关键字来定义一个类,除非使用static关键字。你可以通过将类声明为sealed并使用私有构造函数来实现类似的功能,但它不会在编译后的IL中被标记为abstract,也不会具有编译器确保只能放置static成员的便利特性。 - Tim S.
6
当你将abstract sealed class翻译成VB.NET语言时,得到的是MustInherit CannotInherit Class - H H
显示剩余10条评论
3个回答

11

经检查System.Directory类(IL为静态)的IL代码,其声明如下:

.class public auto ansi abstract sealed beforefieldinit System.IO.Directory
extends System.Object
{
    ...

此外,这篇文章(http://msdn.microsoft.com/en-us/library/ms229038.aspx)建议CLR将静态类处理为抽象密封类,以支持那些不支持直接声明静态类(如C++)的语言。

因此,总之,在C#中,静态类是带有私有构造函数的密封抽象类的语法糖。我个人很高兴这样做,因为“static”更容易写,更容易正确使用。


3
根据定义,sealed类使您能够防止类或先前标记为虚拟的某些类成员的继承。 abstract关键字使您能够创建不完整且必须在派生类中实现的类和类成员。 (来源:http://msdn.microsoft.com/en-us/library/ms173150.aspx)
这意味着任何标记为抽象的类都不能被封闭,因为您无法从它进行派生。
您提到的代码没有任何意义。

2
这不是一个有效的答案吗? - Weyland Yutani
1
如果静态类确实编译成密封抽象类,那么你声称密封抽象类毫无意义的说法显然是荒谬的。 - David Arno
1
它们不是。.NET支持静态类,因此它们不会“编译成”密封抽象类。在.NET中不存在这样的东西(密封抽象类)。 - Lasse V. Karlsen
@LasseV.Karlsen,您错了先生。我已经在Telerik的JustCompile中检查了Directory类的IL,并且它在IL中被定义为“class public auto ansi abstract sealed beforefieldinit System.IO.Directory extends System.Object”。没有提到静态。 - David Arno
2
那么IL也缺乏这个概念。该类仍然是静态的,它不会成为实例类。非静态类允许非静态字段和其他成员,而静态类则不允许,这些类在任何情况下都不允许。但我同意,在这里使用术语上我是错误的。 - Lasse V. Karlsen
显示剩余2条评论

1
所有的答案都从技术角度出发,比如:一个类不能同时“必须继承”和“不能继承”。但我认为这不是主要原因,因为明显,“static”就是那样的。 我认为David Amo的回答有点接近真相,他说:“这样做更容易正确实现。”
我相信Anders Hejlsberg在设计C#时的想法是消除歧义,从而减少错误的机会。这就是为什么“virtual”与“override”一起使用(override必须是显式的,而不像Java中那样是隐式的)。在这种情况下,“abstract”+“sealed”将与“static”相同。这是: - 更容易出错(想象一下你在某个地方使用了abstract,然后不小心把它改成了sealed,编译器可以防止这种情况) - 更难处理(想象一下你想在项目中搜索所有的静态类)
所以我的观点是,这整个设计引导开发人员正确地进行事情。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接