C# 使方法在类中都是静态的

C# 使方法在类中都是静态的,c#,C#,我的同事根据我的一个类(它是一个实例类)告诉我,如果类中没有字段(支持字段),只需将类中的所有方法设置为静态,或者将类设置为单例,这样就不必使用关键字new来调用这个BL类中的方法 我想这是常见的好做法?基本面向对象?我只是想看看人们对此的看法 我想他基本上是说,因为没有状态,所以方法不需要是实例方法 在这种情况下,我不确定是否每次都选择单身……这是某种模式还是他给我的好建议 这里是我所说的类(请不要在这个线程中重新发布任何代码,这是私有的):对于什么时候类应该是静态的,没有绝对的规则。它可能没

我的同事根据我的一个类(它是一个实例类)告诉我,如果类中没有字段(支持字段),只需将类中的所有方法设置为静态,或者将类设置为单例,这样就不必使用关键字new来调用这个BL类中的方法

我想这是常见的好做法?基本面向对象?我只是想看看人们对此的看法

我想他基本上是说,因为没有状态,所以方法不需要是实例方法

在这种情况下,我不确定是否每次都选择单身……这是某种模式还是他给我的好建议


这里是我所说的类(请不要在这个线程中重新发布任何代码,这是私有的):

对于什么时候类应该是静态的,没有绝对的规则。它可能没有状态,但您可能需要它来实现引用相等或锁定。当类作为静态类实现时,当它们的用途适合时,类应该是静态的。在这种情况下,你不应该严格遵守规则;使用你“感觉”正确的东西


没有状态使它成为静态的候选者,但在任意重构它之前,先看看它的用途。

听起来像是在谈论一个严格的实用程序类,在这种情况下,没有理由使用单独的实例


使这些实用方法成为静态的。如果愿意,可以将类作为常规对象保留(以便将来添加实例方法/状态信息)。

实用程序类通常由不需要状态的独立方法组成。在这种情况下,最好将这些方法设置为静态。您还可以将该类设置为静态,这样就不能实例化它

使用C#3,您还可以利用扩展方法,这将使用这些方法扩展其他类。请注意,在这种情况下,需要将类设置为静态

public static class MathUtil
{
    public static float Clamp(this float value, float min, float max)
    {
        return Math.Min(max, Math.Max(min, value));
    }
}
用法:

float f = ...;
f.Clamp(0,1);

调用new和构造类引用没有什么坏处,特别是当类没有状态时。NET中的分配速度很快,所以我不会单独用它来证明类是静态的

通常,我觉得如果一个类没有特定的上下文,那么该类应该是静态的——如果您只是将该类用作“实用工具”方法或非上下文特定操作的占位符,那么作为一个静态类是有意义的

如果该类对上下文有特定的需求,并且有具体意义上的含义,那么即使它没有状态(尽管这种情况很少见),它也可能无法证明是静态的。有时,类的用途是由其引用本身定义的,它提供了排序的“状态”(引用本身),而没有任何局部变量


也就是说,静态类和单例类之间有很大的区别。单例是另一种动物——当需要创建类的一个实例(但只有一个实例)时,您希望使用它。单例中存在状态,但您使用此模式强制执行状态只有一个副本。这有一个非常不同的含义,我强烈建议避免使用单例来防止需要“调用新的”。

只要不需要从类中创建任何抽象,静态方法就可以了。如果您的类需要模拟或实现任何类型的接口,那么最好将该类设置为单例,因为您不能模拟类上的静态方法。您可以让单例实现接口,并可以从单例继承实例方法,而不能继承静态方法


我们通常使用单例而不是静态方法,以便于抽象类。这在单元测试中帮助了很多次,因为我们遇到了一些场景,在这些场景中,我们想要模拟一些东西,并且可以很容易地做到这一点,因为该行为是作为单例上的实例方法实现的。

缺少状态本身并不是使方法静态的理由。在很多情况下,无状态类仍然应该是静态的拥有实例方法。例如,每当您需要在例程之间传递某些逻辑的特定实现时,使用具有实例方法的类就更容易了,因为它允许我们使用接口:

interface IConnectionProvider
{
    object GetConnectedObject();
}
我们可以有十几个以上的实现,并将它们传递到需要
IConnectionProvider
的例程中。在这种情况下,静态是一个非常笨拙的选择


必须使用
new
才能在无状态类中使用方法,这没有什么错。

我可以想出很多理由来解释一个没有成员的非静态类。一方面,它可以实现一个接口并提供/增强另一个接口的行为。其次,它可能有允许定制的虚拟或抽象方法。基本上,使用“静态”方法在最坏的情况下是程序化编程,与面向对象的设计背道而驰

话虽如此,通常小型实用程序例程最好通过过程实现来完成,所以如果有意义,请不要回避。考虑String。ISNulLoLunType()是程序静态例程的一个很好的例子,它在非方法中提供了好处。(好处是它还可以检查字符串是否为null)


另一个例子是序列化例程。它不需要任何会员。假设它有两个方法Write(Stream,Object)和objectread(Stream)。不要求这是一个对象,静态方法就足够了;然而,作为一个对象或接口是有意义的。作为一个对象,我可以重写它的行为,或者稍后更改它的实现,以便它缓存有关它序列化的对象类型的信息。通过将它作为一个对象开始,您不会限制自己。

大多数时候,可以将类设置为静态。但更好的问题是,为什么你有一个