以下是MSDN在“何时使用静态类”一节中所说的:

static class CompanyInfo { public static string GetCompanyName() { return "CompanyName"; } public static string GetCompanyAddress() { return "CompanyAddress"; } //... } Use a static class as a unit of organization for methods not associated with particular objects. Also, a static class can make your implementation simpler and faster because you do not have to create an object in order to call its methods. It is useful to organize the methods inside the class in a meaningful way, such as the methods of the Math class in the System namespace.

对我来说,这个例子似乎没有涵盖静态类的很多可能的使用场景。在过去,我曾将静态类用于相关函数的无状态套件,但仅此而已。那么,在什么情况下应该(和不应该)将类声明为静态的呢?


对于c# 3.0,扩展方法可能只存在于顶级静态类中。


我只对辅助方法使用静态类,但随着c# 3.0的出现,我更愿意为这些方法使用扩展方法。

我很少使用静态类方法,原因与我很少使用单例“设计模式”相同。


我在之前的Stack Overflow回答中写下了我对静态类的想法: 类使用单一方法—最佳方法?

我曾经喜欢充满静态方法的实用程序类。他们对辅助方法进行了很大的整合,否则这些方法会导致冗余和维护的麻烦。它们非常容易使用,没有实例化,没有处理,只是“fire'n'forget”。我想这是我第一次无意中尝试创建面向服务的体系结构——许多无状态服务只做它们的工作,而不做其他事情。然而,随着系统的发展,龙将会到来。

多态性

Say we have the method UtilityClass.SomeMethod that happily buzzes along. Suddenly we need to change the functionality slightly. Most of the functionality is the same, but we have to change a couple of parts nonetheless. Had it not been a static method, we could make a derivate class and change the method contents as needed. As it's a static method, we can't. Sure, if we just need to add functionality either before or after the old method, we can create a new class and call the old one inside of it - but that's just gross.

接口问题

由于逻辑原因,静态方法不能通过接口定义。因为我们不能重写静态方法,所以当我们需要通过接口传递静态类时,它们是无用的。这使得我们无法将静态类用作策略模式的一部分。我们可以通过传递委托而不是接口来修补一些问题。

测试

这基本上与上面提到的界面问题密切相关。由于我们交换实现的能力非常有限,我们也会在用测试代码替换生产代码时遇到麻烦。同样,我们可以将它们包装起来,但这将需要我们更改大部分代码,以便能够接受包装器而不是实际的对象。

促进团

由于静态方法通常用作实用方法,而实用方法通常有不同的目的,我们很快就会得到一个充满不一致功能的大类——理想情况下,每个类在系统中都应该有一个单一的目的。只要目的明确,我宁愿上五倍的课。

蠕变参数

To begin with, that little cute and innocent static method might take a single parameter. As functionality grows, a couple of new parameters are added. Soon further parameters are added that are optional, so we create overloads of the method (or just add default values, in languages that support them). Before long, we have a method that takes 10 parameters. Only the first three are really required, parameters 4-7 are optional. But if parameter 6 is specified, 7-9 are required to be filled in as well... Had we created a class with the single purpose of doing what this static method did, we could solve this by taking in the required parameters in the constructor, and allowing the user to set optional values through properties, or methods to set multiple interdependent values at the same time. Also, if a method has grown to this amount of complexity, it most likely needs to be in its own class anyway.

要求使用者毫无理由地创建类的实例

One of the most common arguments is: Why demand that consumers of our class create an instance for invoking this single method, while having no use for the instance afterwards? Creating an instance of a class is a very very cheap operation in most languages, so speed is not an issue. Adding an extra line of code to the consumer is a low cost for laying the foundation of a much more maintainable solution in the future. And finally, if you want to avoid creating instances, simply create a singleton wrapper of your class that allows for easy reuse - although this does make the requirement that your class is stateless. If it's not stateless, you can still create static wrapper methods that handle everything, while still giving you all the benefits in the long run. Finally, you could also make a class that hides the instantiation as if it was a singleton: MyWrapper.Instance is a property that just returns new MyClass();

只有西斯才会做绝对的事

当然,我不喜欢静态方法也有例外。真正的实用程序类不会造成任何膨胀风险,这是静态方法的绝佳案例- System。以Convert为例。如果您的项目是一次性的,不需要将来进行维护,那么整个体系结构真的不是很重要——静态或非静态并不重要——但是开发速度很重要。

标准,标准,标准!

使用实例方法并不会限制您使用静态方法,反之亦然。只要区分的背后是有原因的,而且是标准化的。没有什么比查看一个扩展了不同实现方法的业务层更糟糕的了。


我使用静态类作为定义给定类型的对象在特定上下文下可以使用的“额外功能”的一种手段。通常它们都是实用程序类。

除此之外,我认为“使用静态类作为与特定对象无关的方法的组织单元”很好地描述了它们的预期用途。


我确实倾向于为工厂使用静态类。例如,这是我的一个项目中的日志类:

public static class Log
{
   private static readonly ILoggerFactory _loggerFactory =
      IoC.Resolve<ILoggerFactory>();

   public static ILogger For<T>(T instance)
   {
      return For(typeof(T));
   }

   public static ILogger For(Type type)
   {
      return _loggerFactory.GetLoggerFor(type);
   }
}

您甚至可能已经注意到IoC是使用静态访问器调用的。对我来说,大多数时候,如果你可以调用一个类的静态方法,这就是你能做的一切,所以我把类标记为静态,以额外的清晰。


如果你使用代码分析工具(例如FxCop),如果一个方法不访问实例数据,它会建议你将该方法标记为静态。其基本原理是有性能增益。CA1822 -将成员标记为静态。

这更像是一个指导方针,而不是规则,真的……


当我希望使用函数而不是类作为重用单元时,我已经开始使用静态类。以前,我对静态类非常反感。然而,学习f#让我从新的角度看待它们。

这是什么意思呢?好吧,比如说在编写一些超级DRY代码时,我最终得到了一堆只有一个方法的类。我可能只是将这些方法拉到一个静态类中,然后使用委托将它们注入到依赖项中。这也可以很好地使用我选择的依赖注入容器Autofac。

当然,直接依赖静态方法通常仍然是有害的(有一些无害的用途)。


When deciding whether to make a class static or non-static you need to look at what information you are trying to represent. This entails a more 'bottom-up' style of programming where you focus on the data you are representing first. Is the class you are writing a real-world object like a rock, or a chair? These things are physical and have physical attributes such as color, weight which tells you that you may want to instantiate multiple objects with different properties. I may want a black chair AND a red chair at the same time. If you ever need two configurations at the same time then you instantly know you will want to instantiate it as an object so each object can be unique and exist at the same time.

On the other end, static functions tend to lend more to actions which do not belong to a real-world object or an object that you can easily represent. Remember that C#'s predecessors are C++ and C where you can just define global functions that do not exist in a class. This lends more to 'top-down' programming. Static methods can be used for these cases where it doesn't make sense that an 'object' performs the task. By forcing you to use classes this just makes it easier to group related functionality which helps you create more maintainable code.

大多数类既可以用静态的也可以用非静态的来表示,但是当你有疑问时,只要回到OOP的根源,试着想想你在表示什么。这是一个正在执行动作的对象(一辆可以加速、减速、转弯的汽车)还是更抽象的对象(比如显示输出)?

与你的内部OOP保持联系,你就永远不会出错!


静态类非常有用,有一席之地,例如库。

我能提供的最好的例子是. net Math类,它是一个包含数学函数库的系统名称空间静态类。

这就像任何其他事情一样,使用正确的工具来完成工作,如果没有的话,任何工具都可以滥用。

盲目地认为静态类是错误的,不要使用它们,或者说“只能有一个”或没有,都是错误的,就像过度使用它们一样。

c#。Net包含许多静态类,就像Math类一样。

因此,只要正确实现,它们就非常有用。

我们有一个静态TimeZone类,它包含许多业务相关的时区函数,不需要像Math类那样创建多个类实例,它在静态类中包含一组全局可访问的TimeZone相关函数(方法)。


这是自面向对象开发开始以来另一个古老但非常热门的问题。 当然,使用(或不使用)静态类的原因有很多,其中大多数已经在大量的答案中涵盖了。

我想说的是,我让一个类是静态的,当这个类在系统中是唯一的并且在程序中有它的实例是没有意义的。但是,我将这种用法保留给大型类使用。我从来没有将MSDN示例中这样的小类声明为“静态的”,当然,也没有将成为其他类成员的类。

我还想指出,静态方法和静态类是两种不同的东西。在已接受的答案中提到的主要缺点是针对静态方法。静态类提供了与普通类相同的灵活性(涉及属性和参数),其中使用的所有方法都应该与类存在的目的相关。

在我看来,静态类候选的一个很好的例子是“FileProcessing”类,它将包含与程序的各种对象相关的所有方法和属性,以执行复杂的FileProcessing操作。拥有这个类的多个实例几乎没有任何意义,而静态将使程序中的任何东西都可以随时使用它。


基于MSDN:

不能为静态类创建实例 如果类声明为静态,则该类的成员变量应该是静态的 密封[不可继承] 不能包含实例构造函数 内存管理

示例:数学计算(数学值)不会改变[定义值的标准计算]