何时在 C# 中使用静态类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/241339/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 19:28:19  来源:igfitidea点击:

When to use static classes in C#

c#classstatic

提问by pbh101

Here's what MSDN has to say under When to Use Static Classes:

以下是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.

static class CompanyInfo
{
    public static string GetCompanyName() { return "CompanyName"; }
    public static string GetCompanyAddress() { return "CompanyAddress"; }
    //...
}

使用静态类作为与特定对象无关的方法的组织单位。此外,静态类可以使您的实现更简单、更快,因为您不必创建对象来调用其方法。以有意义的方式组织类内部的方法很有用,例如 System 命名空间中 Math 类的方法。

To me, that example doesn't seem to cover very many possible usage scenarios for static classes. In the past I've used static classes for stateless suites of related functions, but that's about it. So, under what circumstances should (and shouldn't) a class be declared static?

对我而言,该示例似乎并未涵盖静态类的许多可能使用场景。过去,我将静态类用于相关函数的无状态套件,但仅此而已。那么,在什么情况下应该(也不应该)将类声明为静态?

采纳答案by Mark S. Rasmussen

I wrote my thoughts of static classes in an earlier Stack Overflow answer: Class with single method -- best approach?

我在较早的 Stack Overflow 回答中写下了我对静态类的想法: Class with single method -- best approach?

I used to love utility classes filled up with static methods. They made a great consolidation of helper methods that would otherwise lie around causing redundancy and maintenance hell. They're very easy to use, no instantiation, no disposal, just fire'n'forget. I guess this was my first unwitting attempt at creating a service-oriented architecture - lots of stateless services that just did their job and nothing else. As a system grows however, dragons be coming.

我曾经喜欢充满静态方法的实用程序类。他们对辅助方法进行了很好的整合,否则会导致冗余和维护地狱。它们非常易于使用,无需实例化,无需处理,只需触发'n'forget。我想这是我第一次在不知情的情况下尝试创建面向服务的架构——许多无状态服务只是完成了他们的工作,没有别的。然而,随着系统的发展,龙即将到来。

Polymorphism

多态性

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.

假设我们有方法 UtilityClass.SomeMethod ,它很高兴地嗡嗡作响。突然间,我们需要稍微改变一下功能。大多数功能是相同的,但我们必须更改几个部分。如果它不是静态方法,我们可以创建一个派生类并根据需要更改方法内容。由于它是静态方法,我们不能。当然,如果我们只需要在旧方法之前或之后添加功能,我们可以创建一个新类并在其中调用旧的类 - 但这太糟糕了。

Interface woes

接口问题

Static methods cannot be defined through interfaces for logic reasons. And since we can't override static methods, static classes are useless when we need to pass them around by their interface. This renders us unable to use static classes as part of a strategy pattern. We might patch some issues up by passing delegates instead of interfaces.

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

Testing

测试

This basically goes hand in hand with the interface woes mentioned above. As our ability of interchanging implementations is very limited, we'll also have trouble replacing production code with test code. Again, we can wrap them up, but it'll require us to change large parts of our code just to be able to accept wrappers instead of the actual objects.

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

Fosters blobs

培养斑点

As static methods are usually used as utility methods and utility methods usually will have different purposes, we'll quickly end up with a large class filled up with non-coherent functionality - ideally, each class should have a single purpose within the system. I'd much rather have a five times the classes as long as their purposes are well defined.

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

Parameter creep

参数蠕变

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.

首先,这个可爱而天真的静态方法可能只需要一个参数。随着功能的增长,添加了几个新参数。很快就会添加更多可选参数,因此我们创建方法的重载(或仅添加默认值,使用支持它们的语言)。不久,我们就有了一个接受 10 个参数的方法。只有前三个是真正需要的,参数 4-7 是可选的。但是如果指定了参数6,7-9也需要填写...如果我们创建一个类的目的是做这个静态方法所做的事情,我们可以通过在构造函数,并允许用户通过属性设置可选值,或同时设置多个相互依赖的值的方法。此外,如果一个方法已经发展到这种复杂程度,

Demanding consumers to create an instance of classes for no reason

要求消费者无缘无故地创建类的实例

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();

最常见的论点之一是:为什么要求我们的类的使用者创建一个实例来调用这个单一方法,而之后却不再使用该实例?在大多数语言中,创建一个类的实例是一个非常便宜的操作,所以速度不是问题。向消费者添加额外的一行代码是一种低成本,可以为未来更易于维护的解决方案奠定基础。最后,如果您想避免创建实例,只需为您的类创建一个单例包装器,以便轻松重用——尽管这确实要求您的类是无状态的。如果它不是无状态的,您仍然可以创建处理所有内容的静态包装器方法,同时从长远来看仍然为您提供所有好处。最后,new MyClass();

Only a Sith deals in absolutes

只有西斯处理绝对的

Of course, there are exceptions to my dislike of static methods. True utility classes that do not pose any risk to bloat are excellent cases for static methods - System.Convert as an example. If your project is a one-off with no requirements for future maintenance, the overall architecture really isn't very important - static or non static, doesn't really matter - development speed does, however.

当然,我不喜欢静态方法也有例外。不会造成任何膨胀风险的真正实用程序类是静态方法的极好案例 - 以 System.Convert 为例。如果你的项目是一次性的,不需要未来的维护,那么整体架构真的不是很重要——静态或非静态,并不重要——然而,开发速度很重要。

Standards, standards, standards!

标准,标准,标准!

Using instance methods does not inhibit you from also using static methods, and vice versa. As long as there's reasoning behind the differentiation and it's standardised. There's nothing worse than looking over a business layer sprawling with different implementation methods.

使用实例方法不会阻止您也使用静态方法,反之亦然。只要差异化背后有推理,并且是标准化的。没有什么比查看具有不同实现方法的业务层更糟糕的了。

回答by Mark Cidade

For C# 3.0, extension methods may only exist in top-level static classes.

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

回答by jonnii

I only use static classes for helper methods, but with the advent of C# 3.0, I'd rather use extension methods for those.

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

I rarely use static classes methods for the same reasons why I rarely use the singleton "design pattern".

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

回答by Trap

I use static classes as a means to define "extra functionality" that an object of a given type could use under a specific context. Usually they turn out to be utility classes.

我使用静态类来定义给定类型的对象可以在特定上下文中使用的“额外功能”。通常它们是实用程序类。

Other than that, I think that "Use a static class as a unit of organization for methods not associated with particular objects." describe quite well their intended usage.

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

回答by Rob

I do tend to use static classes for factories. For example, this is the logging class in one of my projects:

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

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);
   }
}

You might have even noticed that IoC is called with a static accessor. Mostof the time for me, if you can call static methods on a class, that's all you can do so I mark the class as static for extra clarity.

您甚至可能已经注意到 IoC 是使用静态访问器调用的。 对我来说,大多数时候,如果您可以在类上调用静态方法,那就是您所能做的所有事情,因此为了更加清晰,我将类标记为静态。

回答by user25306

If you use code analysis tools (e.g. FxCop), it will recommend that you mark a method staticif that method don't access instance data. The rationale is that there is a performance gain. MSDN: CA1822 - Mark members as static.

如果您使用代码分析工具(例如FxCop),static如果该方法不访问实例数据,它会建议您标记该方法。其基本原理是性能提升。MSDN:CA1822 - 将成员标记为 static

It is more of a guideline than a rule, really...

它更像是一个指南而不是规则,真的……

回答by bentayloruk

I've started using static classes when I wish to use functions, rather than classes, as my unit of reuse. Previously, I was all about the evil of static classes. However, learning F#has made me see them in a new light.

当我希望使用函数而不是类作为我的重用单元时,我已经开始使用静态类。以前,我是关于静态类的邪恶。但是,学习F#使我对它们有了新的认识。

What do I mean by this? Well, say when working up some super DRYcode, I end up with a bunch of one-method classes. I may just pull these methods into a static class and then inject them into dependencies using a delegate. This also plays nicely with my dependency injection(DI) container of choice Autofac.

我这是什么意思?好吧,假设在处理一些超级DRY代码时,我最终会得到一堆单一方法类。我可能只是将这些方法拉入一个静态类,然后使用委托将它们注入到依赖项中。这也很好地与我选择的 Autofac 的依赖注入(DI) 容器配合使用。

Of course taking a direct dependency on a static method is still usuallyevil (there are some non-evil uses).

当然,直接依赖静态方法通常仍然邪恶的(有一些非邪恶的用途)。

回答by Despertar

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.

另一方面,静态函数倾向于为不属于现实世界对象或您可以轻松表示的对象的动作提供更多信息。请记住,C# 的前身是 C++ 和 C,您可以在其中定义类中不存在的全局函数。这更适合“自上而下”的编程。静态方法可用于这些“对象”执行任务没有意义的情况。通过强制您使用类,这只会让相关功能更容易分组,从而帮助您创建更易于维护的代码。

Most classes can be represented by either static or non-static, but when you are in doubt just go back to your OOP roots and try to think about what you are representing. Is this an object that is performing an action (a car that can speed up, slow down, turn) or something more abstract (like displaying output).

大多数类都可以用静态或非静态表示,但是当您有疑问时,只需回到您的 OOP 根源并尝试考虑您所表示的内容。这是一个正在执行动作的对象(一辆可以加速、减速、转弯的汽车)还是更抽象的东西(比如显示输出)。

Get in touch with your inner OOP and you can never go wrong!

与您内心的 OOP 保持联系,您永远不会出错!

回答by Don

Static classes are very useful and have a place, for example libraries.

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

The best example I can provide is the .Net Math class, a System namespace static class that contains a library of maths functions.

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

It is like anything else, use the right tool for the job, and if not anything can be abused.

就像其他任何事情一样,使用正确的工具来完成工作,否则任何东西都可能被滥用。

Blankly dismissing static classes as wrong, don't use them, or saying "there can be only one" or none, is as wrong as over using the them.

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

C#.Net contains a number of static classes that is uses just like the Math class.

C#.Net 包含许多静态类,就像 Math 类一样使用。

So given the correct implementation they are tremendously useful.

因此,鉴于正确的实施,它们非常有用。

We have a static TimeZone class that contains a number of business related timezone functions, there is no need to create multiple instances of the class so much like the Math class it contains a set of globally accesible TimeZone realated functions (methods) in a static class.

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

回答by ThunderGr

This is another old but very hot question since OOP kicked in. There are many reasons to use(or not) a static class, of course and most of them have been covered in the multitude of answers.

这是自 OOP 出现以来另一个古老但非常热门的问题。使用(或不使用)静态类的原因有很多,当然,其中大多数已经在众多答案中涵盖。

I will just add my 2 cents to this, saying that, I make a class static, when this class is something that would be unique in the system and that would really make no sense to have any instances of it in the program. However, I reserve this usage for big classes. I never declare such small classes as in the MSDN example as "static" and, certainly, not classes that are going to be members of other classes.

我将为此添加我的 2 美分,说,当这个类在系统中是独一无二的并且在程序中拥有它的任何实例时真的没有意义时,我将类设为静态。但是,我将这种用法保留给大类。我从来没有将像 MSDN 示例中那样的小类声明为“静态”,当然,也不会声明将成为其他类成员的类。

I also like to note that static methodsand static classesare two different things to consider. The main disadvantages mentioned in the accepted answer are for static methods. static classesoffer the same flexibility as normal classes(where properties and parameters are concerned), and all methods used in them should be relevant to the purpose of the existence of the class.

我还想指出,静态方法和静态是需要考虑的两个不同的事情。接受的答案中提到的主要缺点是静态方法。静态提供与普通类(涉及属性和参数)相同的灵活性,并且其中使用的所有方法都应与类存在的目的相关。

A good example, in my opinion, of a candidate for a static class is a "FileProcessing" class, that would contain all methods and properties relevant for the program's various objects to perform complex FileProcessing operations. It hardly has any meaning to have more than one instance of this class and being static will make it readily available to everything in your program.

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