【问题标题】:In C#, what is the purpose of marking a class static?在 C# 中,将类标记为静态的目的是什么?
【发布时间】:2010-02-11 22:19:27
【问题描述】:

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

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

我环顾四周,看到了一些类似的问题,但没有一个是这样的。

【问题讨论】:

标签: c# .net class-design


【解决方案1】:

将类标记为静态是一种声明性声明,您只打算让该类型具有静态和常量成员。这是由编译器强制执行的,可防止您意外向类型添加实例方法。

其他优势

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

【讨论】:

  • 它还阻止消费者创建类的实例。在引入静态类之前,您必须创建一个私有的无参数构造函数来强制执行此操作。
  • 顺便说一句,将类设为静态还可以防止将该类型用作泛型类、结构、接口、委托或方法的泛型类型参数。 (你会用这样的类型作为泛型类型参数做什么?你不能创建它,所以该类型的任何变量都不会是非空的。你不能通过类型参数调用静态方法。它会是完全没用,所以我们不允许。)
  • 它也不可能从中派生出来(至少我不知道,也许你可以编写自己的 IL 来做之类的),我想这很明显:)
  • @Eric,有趣的是我不知道通用参数预防
  • @Skurmedel:静态类实际上是通过创建一个元数据标记为“密封”和“抽象”的类来实现的。所以不,即使使用 IL 技巧也无法从中派生,因为它是密封的。
【解决方案2】:

将课程标记为static 可以获得两件重要的事情。

  • 编译器验证您只将static 成员放入类中。

  • 向您的代码读者明确说明,该类只是static 成员的容器。

该功能是针对 NDP v1.0 中的一个错误而发明的,其中a un-callable non-static member was included in the System.Environment class

【讨论】:

  • 旁白:我希望在类型上使用类似的readonly 修饰符,这要求所有字段都标记为readonly 并且属于标记为readonly 的类型。必须对 NDP 进行相应的注释,尤其是原始类型。不幸的是,有大量代码是用可变习语编写的(例如List<T>,所以为时已晚。
【解决方案3】:

如果您想编写扩展方法,则必须使用静态类。否则就是显示该类永远不会有任何实例数据。

【讨论】:

    【解决方案4】:

    这是特定于 C# 语言的约定,CLR 没有静态类的概念。它确保您不会在类中意外添加实例成员,无法继承该类以及客户端代码不会意外创建该类的实例。该类的基础 TypeAttributes 是 Abstract 和 Sealed。 Abstract 保证 new 运算符不能工作,Sealed 保证不能从类继承。

    同样按照惯例,扩展方法必须是静态类的静态成员。 VB.NET 的做法不同,它需要 [Extension] 属性。

    在您的代码中使用静态类不是必需的,但它很有用。他们的合同非常具有描述性,它使您的代码更容易理解。但请注意不要将它们用作编写过程代码而不是 OOP 代码的工具。

    【讨论】:

    • +1 了解实现细节并提及过度使用编写程序代码。
    【解决方案5】:

    如果你想强制一个类只包含静态方法,你标记一个静态类,一个典型的帮助类。如果你放置一个实例方法,编译器会抱怨——这很好。在 .NET 框架的第 1 版中,有一个类,不记得是哪一个了,它只包含静态方法。意外地,其中一种方法没有获得静态修饰符。因为这个功能在发布后很晚才发现错误时不存在。他们确实将构造函数设为私有,因此无法使用该方法。

    【讨论】:

      猜你喜欢
      • 2010-10-25
      • 2014-09-27
      • 2010-09-13
      • 1970-01-01
      • 2012-02-03
      • 2012-08-03
      • 2014-12-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多