以下是MSDN在何时使用静态类时要说的内容:
static class CompanyInfo { public static string GetCompanyName() { return "CompanyName"; } public static string GetCompanyAddress() { return "CompanyAddress"; } //... }使用静态类作为与特定对象无关的方法的组织单位.此外,静态类可以使您的实现更简单,更快,因为您不必创建对象来调用其方法.以有意义的方式组织类中的方法很有用,例如System命名空间中Math类的方法.
对我来说,这个例子似乎并没有涵盖静态类的很多可能的使用场景.在过去,我已经将静态类用于相关函数的无状态套件,但这就是它.那么,在什么情况下应该(而且不应该)将一个类声明为静态?
我在早期的Stack Overflow回答中编写了我对静态类的想法: 使用单一方法的类 - 最佳方法?
我曾经喜欢充满静态方法的实用工具类.他们对辅助方法进行了很好的整合,否则会导致冗余和维护.它们非常容易使用,没有实例化,没有处置,只是火不会忘记.我想这是我第一次不知不觉地尝试创建面向服务的体系结构 - 许多无状态服务只是完成了自己的工作而没有其他工作.然而,随着系统的发展,龙将会到来.
多态性
假设我们有方法UtilityClass.SomeMethod愉快地嗡嗡作响.突然间我们需要稍微改变功能.大多数功能都是相同的,但我们必须改变几个部分.如果它不是静态方法,我们可以创建一个派生类并根据需要更改方法内容.因为它是一种静态方法,我们不能.当然,如果我们只需要在旧方法之前或之后添加功能,我们可以创建一个新类并在其中调用旧类 - 但这只是粗略的.
界面困境
由于逻辑原因,无法通过接口定义静态方法.由于我们无法覆盖静态方法,因此当我们需要通过接口传递静态类时,静态类是无用的.这使我们无法使用静态类作为策略模式的一部分.我们可能通过传递代理而不是接口来修补一些问题.
测试
这基本上与上面提到的界面问题密切相关.由于我们交换实现的能力非常有限,我们也很难用测试代码替换生产代码.同样,我们可以将它们包装起来,但它需要我们更改代码的大部分内容,以便能够接受包装而不是实际的对象.
促进blob
由于静态方法通常用作实用方法,而实用方法通常会有不同的用途,我们很快就会得到一个充满非连贯功能的大类 - 理想情况下,每个类在系统中应该有一个目的.只要他们的目的很明确,我宁愿拥有五次课程.
参数蠕变
首先,这个小巧可爱且无辜的静态方法可能需要一个参数.随着功能的增长,添加了几个新参数.很快又添加了可选的参数,因此我们创建了方法的重载(或者只是在支持它们的语言中添加默认值).不久,我们有一个方法,需要10个参数.实际上只需要前三个,参数4-7是可选的.但是如果指定参数6,则需要填写7-9 ...如果我们创建了一个具有执行此静态方法的单一目的的类,我们可以通过接受所需的参数来解决这个问题.构造函数,并允许用户通过属性或方法设置可选值,以同时设置多个相互依赖的值.此外,如果一种方法已经增长到这种复杂程度,
要求消费者无缘无故地创建类的实例
最常见的一个论点是:为什么要求我们类的使用者创建一个用于调用这个方法的实例,而之后却没有使用该实例?在大多数语言中创建类的实例是非常便宜的操作,因此速度不是问题.向消费者添加额外的代码行是为将来构建更易维护的解决方案奠定基础的低成本.最后,如果你想避免创建实例,只需创建一个类的单例包装器,以便于重用 - 尽管这确实要求你的类是无状态的.如果它不是无状态的,你仍然可以创建处理所有内容的静态包装方法,同时从长远来看仍然可以带来所有好处.最后,new MyClass();
只有一个西斯交易绝对
当然,我不喜欢静态方法.对静态方法没有任何风险的真实实用程序类是静态方法的优秀案例 - 以System.Convert为例.如果您的项目是一次性的,对未来的维护没有要求,那么整体架构确实不是很重要 - 静态或非静态,并不重要 - 然而,开发速度确实如此.
标准,标准,标准!
使用实例方法不会阻止您使用静态方法,反之亦然.只要有分化背后的推理并且它是标准化的.没有什么比查看具有不同实现方法的业务层更糟糕的了.
在决定是将类设置为静态还是非静态时,您需要查看要尝试表示的信息.这需要更" 自下而上 "的编程风格,您可以专注于首先代表的数据.您正在写的课程是真实世界的对象,如摇滚乐还是椅子?这些东西是物理的,并且具有物理属性,例如颜色,重量,它告诉您可能想要实例化具有不同属性的多个对象.我可能同时想要一把黑色椅子和一把红色椅子.如果您同时需要两个配置,那么您立即知道您将要将其实例化为对象,因此每个对象可以是唯一的并且同时存在.
另一方面,静态函数倾向于为不属于真实世界对象的动作或可以轻易表示的对象提供更多动作.请记住,C#的前身是C++和C,您可以在其中定义类中不存在的全局函数.这为" 自上而下 "的编程带来了更多.静态方法可用于这些情况,即"对象"执行任务没有意义.通过强制您使用类,这样可以更轻松地对相关功能进行分组,从而帮助您创建更易于维护的代码.
大多数类可以用静态或非静态来表示,但是当你有疑问时,只需回到你的OOP根源并尝试考虑你所代表的内容.这是一个执行动作的对象(可以加速,减速,转弯的汽车)还是更抽象的东西(比如显示输出).
与您的内在OOP保持联系,您永远不会出错!
对于C#3.0,扩展方法可能只存在于顶级静态类中.
如果使用代码分析工具(例如FxCop),则建议您在方法static
不访问实例数据时标记方法.理由是有一个性能提升.MSDN:CA1822 - 将成员标记为静态.
它更像是指导而非规则,真的......
我倾向于为工厂使用静态类.例如,这是我的一个项目中的日志记录类:
public static class Log { private static readonly ILoggerFactory _loggerFactory = IoC.Resolve(); public static ILogger For (T instance) { return For(typeof(T)); } public static ILogger For(Type type) { return _loggerFactory.GetLoggerFor(type); } }
您甚至可能已经注意到使用静态访问器调用IoC. 大部分时间对我来说,如果你可以在一个类上调用静态方法,那就是你所能做到的所有事情我将这个类标记为静态以便更加清晰.
当我希望使用函数而不是类作为我的重用单元时,我开始使用静态类.以前,我只是关于静态类的邪恶.然而,学习F#让我以全新的眼光看待它们.
这是什么意思?好吧,比如在处理一些超级DRY代码时,我最终得到了一堆单方法类.我可能只是将这些方法拉入静态类,然后使用委托将它们注入依赖项.这也适用于我选择Autofac的依赖注入(DI)容器.
当然,直接依赖静态方法仍然是邪恶的(有一些非邪恶的用法).
静态类非常有用,并且有一个位置,例如库.
我能提供的最好的例子是.Net Math类,一个包含数学函数库的System命名空间静态类.
就像其他任何事情一样,使用正确的工具来完成工作,如果没有,可以滥用任何东西.
茫然地将静态类视为错误,不使用它们,或者说"只能有一个"或者没有,就像使用它们一样错误.
C#.Net包含许多静态类,它们与Math类一样使用.
因此,如果正确实施,它们将非常有用.
我们有一个静态TimeZone类,它包含许多与业务相关的时区函数,不需要创建类的多个实例,就像Math类一样,它包含一组静态类中全局可访问的TimeZone相关函数(方法) .
我使用静态类作为定义给定类型的对象可以在特定上下文下使用的"额外功能"的手段.通常它们会变成实用类.
除此之外,我认为"使用静态类作为与特定对象无关的方法的组织单位." 很好地描述了他们的用途.
这是另一个古老而又非常热门的问题,因为OOP开始了.当然,有许多理由使用(或不使用)静态类,其中大多数已被大量答案所涵盖.
我只想加上我的2美分,说,我把一个类设为静态,当这个类在系统中是独一无二的时候,在程序中有任何实例是没有意义的.但是,我保留这个用于大班的用法.我从未在MSDN示例中将这样的小类声明为"静态",当然也不是将要成为其他类成员的类.
我还要注意静态方法和静态类是要考虑的两个不同的东西.接受的答案中提到的主要缺点是静态方法.静态类提供与普通类(涉及属性和参数)相同的灵活性,并且它们中使用的所有方法都应该与类的存在目的相关.
在我看来,静态类的候选者的一个很好的例子是"FileProcessing"类,它包含与程序的各种对象相关的所有方法和属性,以执行复杂的FileProcessing操作.拥有这个类的多个实例几乎没有任何意义,并且静态将使它可以随时用于程序中的所有内容.