可以在C#中覆盖静态方法吗?

我被告知static方法是隐式final ,因此不能被覆盖。 真的吗?

  1. 有人可以提供一个更好的覆盖静态方法的例子吗?

  2. 如果静态方法只是类方法,那么拥有它们的真正用途是什么?

(1)静态方法不能被覆盖,但可以使用’new’关键字隐藏它们。 大多数重写方法意味着您引用基类型并希望调用派生方法。 因为静态是类型的一部分,并且不受vtable查找的影响,这些查找没有意义。

例如静力不能做:

 public class Foo { public virtual void Bar() { ... } } public class Bar : Foo { public override void Bar() { ... } } // use: Foo foo = new Bar(); // make an instance foo.Bar(); // calls Bar::Bar 

由于静态不适用于实例,因此请始终明确指定Foo.Bar或Bar.Bar。 所以覆盖在这里没有任何意义(尝试在代码中表达它……)。

(2)静态方法有不同的用法。 例如,它在Singleton模式中用于获取类型的单个实例。 另一个例子是’static void Main’,它是程序中的主要访问点。

基本上,只要您不想要或在使用它之前无法创建对象实例,就可以使用它们。 例如,静态方法创建对象时。

[更新]

一个简单的隐藏示例:

 public class StaticTest { public static void Foo() { Console.WriteLine("Foo 1"); } public static void Bar() { Console.WriteLine("Bar 1"); } } public class StaticTest2 : StaticTest { public new static void Foo() { Console.WriteLine("Foo 2"); } public static void Some() { Foo(); Bar(); } // Will print Foo 2, Bar 1 } public class TestStatic { static void Main(string[] args) { StaticTest2.Foo(); StaticTest2.Some(); StaticTest.Foo(); Console.ReadLine(); } } 

请注意,如果将类设为static ,则无法执行此操作。 静态类必须从object派生。

这与inheritance之间的主要区别在于编译器可以在编译时确定在使用静态时调用哪个方法。 如果您有对象实例,则需要在运行时执行此操作(称为vtable查找)。

那么你不能覆盖静态方法。 静态方法不能是虚拟的,因为它与类的实例无关。

派生类中的“overriden”方法实际上是一个新方法,与基类中定义的方法无关(因此是new关键字)。

这是一个重要的事情要理解:当类型inheritance自其他类型时,它们实现了一个共同的契约,而静态类型不受任何契约的约束(从纯OOP的角度来看)。 语言中没有技术方法可以将两个静态类型与“inheritance”契约联系起来。 如果你在两个不同的地方“覆盖”Log方法。

如果你考虑过静态方法,它就没有意义; 为了进行虚拟调度,您需要一个要检查的对象的实际实例。

静态方法也无法实现接口; 如果这个类正在实现一个IRolesService接口,那么我认为该方法根本不应该是静态的。 有一个实例方法更好的设计,所以当你准备好时你可​​以用真实的服务换掉你的MockRoleService

您不会覆盖静态方法。 你隐藏它。 有关详细信息,请参阅此答案 。

使用静态方法的一些原因:

  1. 它们比实例方法快一点。 另请参阅这篇msdn文章 ,它提供了性能数据来支持这一点(内联静态调用平均0.2 ns,静态调用avg 6.1ns,内联实例调用avg 1.1 ns,实例调用avg 6.8 ns)
  2. 写出更简洁 – 不需要实例化一个类来获取它们(并且实例化也会影响性能)