何时在c#中使用静态类

这是MSDN必须在下说何时使用静态类:

static class CompanyInfo
{
public static string GetCompanyName() { return "CompanyName"; }
public static string GetCompanyAddress() { return "CompanyAddress"; }
//...
}
使用静态类作为的单位 方法的组织 与特定对象相关联。 此外,静态类可以使您的 实现更简单更快 因为你不需要创建 对象来调用它的方法。 组织这些方法是有用的 以一种有意义的方式, 比如数学课的方法

.在System命名空间

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

509264 次浏览

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

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

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

我在之前的Stack Overflow回答中写了我对静态类的想法: # EYZ0 < / em >

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

多态性

假设我们有一个方法UtilityClass。SomeMethod愉快地嗡嗡作响。突然间,我们需要稍微改变一下功能。大多数功能是相同的,但我们必须改变几个部分。如果它不是一个静态方法,我们可以创建一个派生类,并根据需要更改方法内容。因为它是一个静态方法,我们不能这样做。当然,如果我们只需要在旧方法之前或之后添加功能,我们可以创建一个新类,并在其中调用旧类——但这只是恶心。

接口问题

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

测试

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

促进团

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

蠕变参数

首先,这个可爱而无害的静态方法可能只有一个参数。随着功能的增长,会添加几个新参数。很快,更多可选的参数被添加进来,因此我们创建了方法的重载(或者用支持它们的语言添加默认值)。不久之后,我们就有了一个带有10个参数的方法。只有前三个参数是必需的,参数4-7是可选的。但如果指定参数6,还需要填写7-9个…如果我们创建了一个类,目的只有一个,就是做这个静态方法所做的事情,那么我们就可以通过在构造函数中引入必要的参数来解决这个问题,并允许用户通过属性设置可选值,或者通过方法同时设置多个相互依赖的值。此外,如果一个方法已经发展到这种复杂程度,它很可能无论如何都需要在自己的类中。

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

最常见的争论之一是:为什么要求我们类的使用者为调用这个方法创建一个实例,而之后又不使用这个实例呢?在大多数语言中,创建类的实例是非常非常便宜的操作,所以速度不是问题。向使用者添加额外的代码行是为将来更可维护的解决方案奠定基础的低成本。最后,如果您想避免创建实例,只需为您的类创建一个易于重用的单例包装器—尽管这确实要求您的类是无状态的。如果它不是无状态的,您仍然可以创建处理所有事情的静态包装器方法,同时仍然从长远来看为您提供所有好处。最后,您还可以创建一个类来隐藏实例化,就像它是一个单例一样:MyWrapper。Instance是一个只返回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),它会建议你标记一个方法static,如果该方法不访问实例数据。其基本原理是有性能增益。# EYZ2。

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

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

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

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

当决定一个类是静态的还是非静态的时,你需要看看你想要表示什么信息。这需要一种更“自底向上”风格的编程,首先关注所表示的数据。您正在编写的类是像石头或椅子这样的现实对象吗?这些东西是物理的,有物理属性,比如颜色,权重,这告诉你你可能想实例化多个具有不同属性的对象。我可能同时想要一把黑椅子和一把红椅子。如果你同时需要两个配置,那么你马上就知道你想将它实例化为一个对象,这样每个对象都可以是唯一的,并且同时存在。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

基于MSDN:

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

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