在C#中,将一个类标记为静态的目的是什么?

26

在C#中,标记一个类为static的目的是什么?

如果我有一个只包含静态方法的类,我可以将其标记为静态的或者不标记。那么,为什么我要标记这个类为静态呢?如果所有的方法都是静态的,并且我打算永远不添加非静态方法,我是否会不想将类标记为静态的?

我查找了一些类似的问题,但没有与此完全相同的。


请提供要翻译的文章内容。 - Jørn Schou-Rode
请提出您自己的问题,@dboarman! - Cheeso
别担心,我不想污染你的问题。只是想提醒一下,有人可能会评论静态成员的线程安全性。 ;) - IAbstract
5个回答

28

将一个类声明为静态的是一种声明性语句,说明你只打算让这个类型拥有静态和常量成员。编译器会强制执行这一点,并防止您意外地向该类型添加实例方法。

其他优点

  • 扩展方法只能在静态类中定义
  • ��止用户创建该类的实例
  • 防止将该类型用作泛型参数(感谢 Eric!)

8
使用静态类也可以防止消费者创建该类的实例。在引入静态类之前,你需要创建一个私有无参数构造函数来实现这一点。 - Joel Mueller
6
顺便提一下,将一个类设为静态还可以防止将该类型用作泛型类、结构体、接口、委托或方法的泛型类型参数。(如果将这样的类型用作泛型类型参数会怎么样呢?你无法创建它,因此永远不会有一个非空的该类型变量。你也无法通过类型参数调用静态方法。它完全没有用处,所以我们不允许这样做。) - Eric Lippert
它也不可能从中派生(至少我所知道的是不行的,也许你可以编写自己的IL来实现这个功能),这一点我想是相当明显的 :) - Skurmedel
@Eric,有趣的是我不知道泛型参数预防。 - JaredPar
@Skurmedel:静态类实际上是通过创建一个元数据标记为“sealed”和“abstract”的类来实现的。因此,即使使用IL技巧,您也无法从中派生,因为它是密封的。 - Eric Lippert
我希望接口可以隐式地成为“静态”类型,这样它们就可以包含“静态”成员。 - Jay Bazuzi

7

附言:我希望类型也有类似的“readonly”修饰符,它要求所有字段都标记为“readonly”,并且是标记为“readonly”的类型。 NDP必须相应地进行注释,特别是基本类型。不幸的是,有大量使用可变习惯用法编写的代码(例如List<T>),所以现在为时已晚。 - Jay Bazuzi

6
如果你想编写扩展方法,你必须使用静态类。否则,这将表明该类永远不会有任何实例数据。

5
这是C#语言特有的约定,CLR没有静态类的概念。它确保您不能意外在类中添加实例成员,不能继承该类,并且客户端代码不能意外创建该类的实例。该类的基础TypeAttributes为Abstract和Sealed。Abstract确保new运算符无法工作,Sealed确保您无法从该类继承。
同样按照约定,扩展方法必须是静态类的静态成员。VB.NET则采用不同的方式,需要使用[Extension]属性。
在代码中使用静态类不是必需的,但非常有用。它们的契约描述非常明确,使您的代码更易于理解。但要小心,不要将其用作编写过程式代码而不是OOP代码的工具。

+1 对于实现细节和提到过度编写过程式代码的提醒。 - si618

1

如果您想强制一个类只包含静态方法,那么可以将其标记为静态。这是一个典型的辅助类。如果您放置了一个实例方法,编译器会抱怨 - 这是好事。在 .NET Framework 的版本 1 中,有一个类(不记得是哪个类了),它只能与静态方法一起使用。意外的是,其中一个方法没有得到静态修饰符。因为当时不存在这个功能,所以这个错误被发现得非常晚,在发布后才被发现。他们确实将构造函数设为私有,因此该方法无法使用。


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