如何避免在 C# 中使用静态类

发布: (2026年1月13日 GMT+8 17:52)
6 min read
原文: Dev.to

Source: Dev.to

请提供您希望翻译的正文内容,我将按照要求保留原始链接、格式和代码块,仅翻译文本部分。

静态类和方法的共同特征

静态类和方法常被用作工具类,为整个应用程序提供全局可访问的函数。例如,与其一次又一次地编写代码将 ‘Y’ 和 ‘N’ 转换为 truefalse,不如把这段逻辑放在一个静态工具类中,在需要的地方重复使用,遵循 Don’t Repeat Yourself 原则。

同样是静态的扩展方法也提供了类似的好处,允许你为现有类型添加可复用的功能。

大多数开发者只把静态类视作这些工具场景,而没有挖掘其全部潜力。下面给出一些示例和最佳实践指南。

示例:工具静态类

public static class ConverterUtils
{
    public static bool CharToBool(char c)
    {
        return c == 'Y' || c == 'y';
    }
}
bool result = ConverterUtils.CharToBool('Y');

示例:扩展方法

public static class CharExtensions
{
    public static bool ToBool(this char c)
    {
        return c == 'Y' || c == 'y';
    }
}
bool result = 'N'.ToBool();

静态类:总体概述

静态类就是只包含静态成员并且拥有私有构造函数以防止实例化的类。将类声明为 static 向编译器和其他开发者表明该类不应被实例化——其成员应直接通过类名访问。

  • 无需实例 – 使用静态成员时不需要创建对象,这使它们非常适合作为全局实用函数。
  • 共享状态(或缺乏状态) – 静态方法无法访问实例数据(非 static 字段/属性),只能访问其他静态成员。这使它们保持无状态,除非使用 static 字段,否则可能在整个应用程序中引入共享状态。

使用静态类和方法的最佳实践

  • 保持静态类无状态 – 避免在其中存储数据或跟踪状态。无状态的静态类高效且安全,因为它们仅依据输入参数运行,并返回结果,不产生副作用。
    .NET 框架中的示例包括 System.ConsoleSystem.Math;像 Console.WriteLineMath.Sqrt 这样的成员接受输入并产生输出,而不依赖内部状态。
  • 适用场景 – 格式化日期、转换图像、执行计算,或任何需要快速、可复用逻辑且不需要维护全局或共享数据的情况。

总之,要有效使用静态类,请确保所有输入都通过方法参数提供,并避免在类内部存储任何状态。

当心静态数据

静态变量在所有线程和实例之间共享,这使得预测它们的值变得困难——任何更改都会影响唯一的共享内存位置。如果静态方法依赖或修改静态数据,在多线程环境中可能会得到不一致的结果。

public static class Calculation
{
    private static int totalCount;
    public static void GetCount()
    {
        totalCount = 0;
        for (int i = 0; i < 10; i++)
        {
            totalCount += i;
            Thread.Sleep(100);
        }
        Console.WriteLine("TOTAL COUNT : {0}", totalCount);
    }
}

在多个线程上运行 GetCount 可能会产生意外结果,因为所有线程共享同一个 totalCount 变量。静态方法默认 不是 线程安全的;你必须自行处理同步。有关更多细节,请参阅 K. Scott Allen 的文章《Static and Thread Safety》(Static and Thread Safety)。

静态类的缺点

  • 紧耦合 – 静态类会使代码紧耦合,难以测试。
  • 隐藏依赖 – 方法可能依赖于在其他地方设置的静态数据,使操作顺序变得重要,可能导致意外结果。
public static class TaxStructure
{
    public static int TaxRate { get; set; }
}

public static class CalculateTax
{
    public static void ShowTax()
    {
        Console.WriteLine(TaxStructure.TaxRate);
    }
}

必须在调用 CalculateTax.ShowTax() 之前设置 TaxStructure.TaxRate。如果不设置,或者顺序错误,输出可能不正确。这个隐藏的依赖会使代码更难维护和测试。

进一步阅读

Back to Blog

相关文章

阅读更多 »

MiniScript 2026 路线图

2026 展望 随着 2025 接近尾声,是时候展望 2026 了!MiniScript 已经八岁。许多编程语言真的进入了它们的……