在C#中可以重写静态方法吗

本文关键字:重写 静态方法 | 更新日期: 2023-09-27 17:58:42

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

  1. 有人能给出一个更好的重写静态方法的例子吗?

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

在C#中可以重写静态方法吗

(1)静态方法不能重写,但可以使用"new"关键字隐藏它们。大多数重写方法意味着您引用基类型并希望调用派生方法。由于static是类型的一部分,不受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派生。

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

你不能重写静态方法。静态方法不能是虚拟的,因为它与类的实例无关。

派生类中的"overrided"方法实际上是一个新方法,与基类中定义的方法无关(因此使用了new关键字)。

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

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

静态方法也不能实现接口;如果这个类实现了一个IRolesService接口,那么我认为这个方法根本不应该是静态的。最好设计一个实例方法,这样当您准备好

时,您就可以用真正的服务替换MockRoleService

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

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

  1. 它们比实例方法快一点。另请参阅这篇msdn文章,它给出了支持这一点的性能数字(内联静态调用平均值0.2 ns,静态调用平均数6.1 ns,内联实例调用平均值1.1 ns,实例调用平均数6.8 ns)
  2. 写起来不那么冗长-不需要实例化一个类就可以访问它们(实例化也会影响性能)