C# 对外部静态方法的多个调用或对调用外部静态方法的一个内部方法的调用

C# 对外部静态方法的多个调用或对调用外部静态方法的一个内部方法的调用,c#,class,oop,methods,static,C#,Class,Oop,Methods,Static,所以我的问题是: 我得到了一个静态类,其中包含一个静态方法,名为: static class A() { public static MethodA() { } } 我得到了另一个类,它将多次调用静态类的MethodA(): static class B() { public static MethodB1() { MethodA() } public static MethodB2() { MethodA()

所以我的问题是:

我得到了一个静态类,其中包含一个静态方法,名为:

static class A() {
     public static MethodA() { }
}
我得到了另一个类,它将多次调用静态类的MethodA():

static class B() {
     public static MethodB1() {
         MethodA()
     }
     public static MethodB2() {
         MethodA()
     }
     public static MethodB3() {
         MethodA()
     }
     public static MethodB4() {
         MethodA()
     }
}
这是正确的方法还是应该这样做(调用内部函数,它是静态方法的唯一引用):

我提出这是一个设计或庸俗的问题,但是否有任何技术优势,如可维护或可伸缩的代码


编辑:甚至性能改进?

这被认为是基于意见的,因为两种方法都有各自的优点。这里的许多开发人员都有自己的偏好,因此在回答这一问题时不放弃自己的观点是很有挑战性的。
在B类中,每个调用直接进入方法A,而在C类中,调用首先必须通过本地方法才能进入方法A。这一额外步骤可能被认为是多余的,因此B类将是首选。
但是,无论出于何种原因,您可能必须将调用从方法A更改为方法D,而不是从尚未创建的类更改为方法D。在这种情况下,您必须在类B中更改四个方法,在类C中只更改一个。因此,类C更易于维护和调整。
因此,两者都有各自的优缺点,B级的性能提升非常小。(字面上是时钟滴答作响!)
所以一般来说,这并不重要,所以我的建议是选择最适合开发人员阅读的解决方案。这意味着添加注释,使用正确的格式,使用清晰的方法名称,并尽量避免重复

后一种说法意味着B级和C级都是坏习惯,就像每一个班级一样。您应该重新考虑将这些方法重塑为单一方法。这可能很棘手,因为这些方法可能有很多不同之处

维姆·滕·布林克(Wim ten Brink)写下了我想要的答案,因此我最多只能对他说的话进行补充:

我讨厌使用静力学。将对一个静态的调用替换为对另一个静态的调用是一件痛苦的事情。由于这个原因,我更喜欢C。它使它易于更换

但实际上我还有两个值得考虑的选择:

1st

由于我讨厌静态,我尽量避免写它们。你所有的类仍然是静态的,把问题传递下去。如果我需要这样的东西,并且它有任何非常量场,我不会把它变成静态场。相反,我会让它成为一个需要类的普通实例。然后创建一个静态字段,该字段接受该类的一个实例。这听起来可能没有什么不同,但它取代了:

static staticsProvider SP = new ImplementationA();

允许快速交换。此外,如果您需要为不同的代码段(SP1和SP2)提供两个或多个不同的实例,那么现在只需要一个额外的静态字段和指令。这是静力学的两大问题。您还可以在类或函数范围中使用实例

现在WPF的方式是“如果你不能改变它,就把它包装成你可以改变的东西!”。那么选项D呢:

//I am not a static
public class D{
    //I am not either
    public void MethodA(){
      //But I do call one for you
      A.MethodA();
    }
}
然后可以创建一个静态字段:

static public D SP = new D();
如果需要多个静态提供程序?做另一个领域。如果您需要不同的实现?从
D
中提取接口(实际上是VSIDE选项)或创建抽象基类。将变量更改为所述基类/接口。然后创建一个D2类,它继承/实现了您刚刚创建的类

不希望它在运行时更改吗?常量或只读修饰符。但实际上,在运行时交换实例的能力可能是一个特性

第二名

与其减少对静态的调用,不如减少MethodBX和MethodCX的版本

通过使用委托,您可以将“beforeStatic”和“afterStatic”部分的代码作为函数提交

然而,这仅适用于非常小的差异。如果您有很大的差异,那么为每个调用编写两个大型委托会比只编写您现在得到的多个函数更难管理

函数调用开销

调用函数是有代价的。实际上,CPU必须进行跳转。跳跃仍然是一种成本可以衡量的东西。这很可能不会在大局中起作用——我们已经远远超过了限制CPU周期的时间。此外,可以自动避免:

本机C++有编译器提示。 Afaik.NET不允许此控件。但它确实有JiT和编译器优化。而这些可以完全去和内联为您的自动。对于这样的函数:

public static StaticCaller() {
  MethodA();
}

我只想说,如果有任何函数要内联,那么看起来像这样的函数必须在列表的顶部。

这些函数有什么不同如果只有一小部分,那么一个带有“beforeStatic”和“afterStatic”函数的委托参数的函数就可以做到这一点如果它们完全没有区别,那么它们就不应该是4个函数|如果它们差异很大,委托可能仍然有效,但是委托声明可能会变得非常大,像现在这样的硬编码函数更好。在这种情况下,我更喜欢StaticCaller方法。静态的问题是:如果需要替换它们怎么办?将调用更改为
MethodA()
everywhere既耗时又容易出错。如果您只需在
StaticCaller()
中执行此操作一次,那么它确实很有帮助。当然,在制作类似于类A的东西时,您应该避免使用静态调用。我的建议是——除了少数例外——分配给静态字段的实例比任何静态类都好。在lesat,你可以有多个并快速替换它们。例外情况是FactoryMethods(必须是静态的或属于类),或者是可变的东西,比如数学类。常量集合也会计数,但我建议尽可能在这里使用枚举。B类和C类都是错误的!
static public D SP = new D();
public static StaticCaller() {
  MethodA();
}