小编典典

何时在 C# 中使用静态类

all

以下是MSDN 在 When to Use Static Classes 下所说的:

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

}
//…
}

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

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


阅读 119

收藏
2022-03-04

共1个答案

小编典典

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

多态性

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

接口问题

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

测试

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

促进斑点

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

参数蠕变

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

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

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

只有西斯在绝对交易

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

标准,标准,标准!

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

2022-03-04