首页 文章

何时在C#中使用静态类[重复]

提问于
浏览
550

这个问题在这里已有答案:

这是MSDN has to say under When to Use Static Classes

静态类CompanyInfo
{
public static string GetCompanyName(){return“CompanyName”; }
public static string GetCompanyAddress(){return“CompanyAddress”; }
// ...
}
将静态类用作与特定对象无关的方法的组织单位 . 此外,静态类可以使您的实现更简单,更快,因为您不必创建对象来调用其方法 . 以有意义的方式组织类中的方法很有用,例如System命名空间中Math类的方法 .

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

11 回答

  • 9

    我使用静态类作为定义给定类型的对象可以在特定上下文下使用的“额外功能”的手段 . 通常他们结果是实用类 .

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

  • 665

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

    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 . 对我来说大部分时间,如果你可以在一个类上调用静态方法,那就是你所能做到的所有事情,我将该类标记为静态,以便更加清晰 .

  • 21

    我只对辅助方法使用静态类,但随着C#3.0的出现,我宁愿使用扩展方法 .

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

  • 133

    基于MSDN

    • 您无法为静态类创建实例

    • 如果类声明为static,则成员变量对于该类应该是静态的

    • 密封[无法继承]

    • 不能包含实例构造函数

    • 内存管理

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

  • 2

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

    我曾经喜欢充满静态方法的实用工具类 . 他们对辅助方法进行了很好的整合,否则会导致冗余和维护 . 它们非常容易使用,没有实例化,没有处理,只是火不会忘记 . 我想这是我第一次不知不觉地尝试创建面向服务的体系结构 - 许多无状态服务只是完成了自己的工作而没有其他工作 . 然而,随着系统的发展,龙将会到来 .

    Polymorphism

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

    Interface woes

    由于逻辑原因,无法通过接口定义静态方法 . 由于我们无法覆盖静态方法,因此当我们需要通过接口传递静态类时,静态类是无用的 . 这使我们无法使用静态类作为策略模式的一部分 . 我们可能会通过passing delegates instead of interfaces修补一些问题 .

    Testing

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

    Fosters blobs

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

    Parameter creep

    首先,这个小巧可爱且无辜的静态方法可能只需要一个参数 . 随着功能的增长,添加了几个新参数 . 很快又添加了可选的参数,因此我们创建了方法的重载(或者只是在支持它们的语言中添加默认值) . 不久,我们有一个方法,需要10个参数 . 实际上只需要前三个,参数4-7是可选的 . 但是如果指定参数6,则需要填写7-9 ...如果我们创建了一个具有执行此静态方法所做的单一目的的类,我们可以通过获取所需的参数来解决这个问题 . 构造函数,并允许用户通过属性或方法设置可选值,以同时设置多个相互依赖的值 . 此外,如果一种方法已经增长到这种复杂程度,那么最多无论如何,可能需要在自己的 class .

    Demanding consumers to create an instance of classes for no reason

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

    Only a Sith deals in absolutes

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

    Standards, standards, standards!

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

  • 7

    当我希望使用函数而不是类作为我的重用单元时,我开始使用静态类 . 以前,我都是关于静态类的邪恶 . 然而,学习F#让我以新的眼光看待它们 .

    这是什么意思?好吧,比如说在处理一些超级代码时,我最终得到了一堆单方法类 . 我可能只是将这些方法拉入静态类,然后使用委托将它们注入依赖项 . 这也适用于我选择Autofac的dependency injection(DI)容器 .

    当然,直接依赖静态方法仍然是邪恶的(有一些非邪恶的用法) .

  • 35

    静态类非常有用,并且有一个位置,例如库 .

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

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

    茫然地将静态类视为错误,不要使用它们,或者说“只能有一个”或者没有,就像使用它们一样错误 .

    C#.Net包含许多静态类,它们与Math类一样使用 .

    因此,如果正确实施,它们将非常有用 .

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

  • 12

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

  • 2

    如果您使用代码分析工具(例如FxCop),则建议您标记方法 static (如果该方法不访问实例数据) . 理由是有一个性能提升 . MSDN: CA1822 - Mark members as static .

    它更像是指导而非规则,真的......

  • 10

    自OOP开始以来,这是另一个古老而又非常热门的问题 . 当然,使用(或不使用)静态类的原因有很多,其中大多数已被大量答案所覆盖 .

    我只想加上我的2美分,说,我把一个类静态化,当这个类在系统中是独一无二的时候,在程序中有任何实例都没有意义 . 但是,我为大班保留了这种用法 . 我从未在MSDN示例中声明这样的小类作为“静态”,当然,不是将成为其他类的成员的类 .

    我还要注意静态方法和静态类是要考虑的两个不同的东西 . 接受的答案中提到的主要缺点是静态方法 . 静态类提供与普通类(涉及属性和参数)相同的灵活性,并且它们中使用的所有方法都应该与类的存在目的相关 .

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

  • 10

    在决定是否上课时静态或非静态您需要查看您尝试表示的信息 . 这需要更加' bottom-up '的编程风格,您可以专注于首先代表的数据 . 您正在写的课程是真实世界的对象,如摇滚乐还是椅子?这些东西是物理的,并且具有物理属性,例如颜色,重量,它告诉您可能想要实例化具有不同属性的多个对象 . 我可能想要一把黑色的椅子和一把红色的椅子 . 如果您同时需要两个配置,那么您立即知道您将要将其实例化为对象,因此每个对象可以是唯一的并且同时存在 .

    另一方面,静态函数倾向于向不属于真实世界对象的动作或可以轻易表示的对象提供更多动作 . 请记住,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有意义'object'执行任务 . 通过强制您使用类,这样可以更轻松地对相关功能进行分组,从而帮助您创建更易于维护的代码 .

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

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

相关问题