C#虚拟(或抽象)静态方法

Nic*_*ley 12 c# inheritance

静态继承就像实例继承一样工作.除非您不允许将静态方法设为虚拟或抽象.

class Program {
    static void Main(string[] args) {
        TestBase.TargetMethod();
        TestChild.TargetMethod();
        TestBase.Operation();
        TestChild.Operation();
    }
}

class TestBase {
    public static void TargetMethod() {
        Console.WriteLine("Base class");
    }

    public static void Operation() {
        TargetMethod();
    }
}

class TestChild : TestBase {
    public static new void TargetMethod() {
        Console.WriteLine("Child class");
    }
}
Run Code Online (Sandbox Code Playgroud)

这将输出:

Base class
Child class
Base class
Base class
Run Code Online (Sandbox Code Playgroud)

但我想要:

Base class
Child class
Base class
Child class
Run Code Online (Sandbox Code Playgroud)

如果我可以在静态方法上,我会使TargetMethod虚拟,它会完成这项工作.但有没有可以达到同样的效果?

编辑:是的,我可以在子类中放置一个Operation副本,但这需要复制并将大量代码粘贴到每个子节点,在我的例子中大约是35个类,这是一个维护噩梦.

Ste*_*ger 13

不,你不能覆盖静态方法."static"也意味着它是由编译器静态绑定的,因此在运行时找不到要调用的实际方法,但在编译时绑定.

你应该做的是使类非静态.使方法成为虚拟并覆盖它并充分利用实际继承.然后,如果您确实需要它,请为您的类的引用创建一个静态入口点.例如一个静态工厂,单例(在大多数情况下它是一个反模式但是和静态类一样好)或者只是一个静态属性.


Mar*_*ett 9

您可以将TargetMethod存储为委托,子类可以根据需要进行更改:

class TestBase {
    protected static Action _targetMethod;

    static new() {
       _targetMethod = new Action(() => {
           Console.WriteLine("Base class");
       });
    }

    public static void TargetMethod() {
        _targetMethod();
    }

    public static void Operation() {
        TargetMethod();
    }
}

class TestChild : TestBase {
    static new() {
       _targetMethod = new Action(() => {
           Console.WriteLine("Child class");
       });
    }
}
Run Code Online (Sandbox Code Playgroud)

因为这些是静态实例,_targetMethod所以它们在所有实例之间共享 - 更改它TestChild也会改变它TestBase.你可能会或可能不会关心这一点.如果你这样做,泛型或者Dictionary<Type, Action>可能有所帮助.

但总的来说,如果你不坚持静态,或者使用组合而不是继承,那么你会有更轻松的时间.