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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/763344/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 00:14:42  来源:igfitidea点击:

C# virtual (or abstract) static methods

c#inheritance

提问by Nick Whaley

Static inheritance works just like instance inheritance. Except you are not allowed to make static methods virtual or abstract.

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

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");
    }
}

This will output:

这将输出:

Base class
Child class
Base class
Base class

But I want:

但我想要:

Base class
Child class
Base class
Child class

If it I could on static methods, I would make TargetMethod virtual and it would do the job. But is there a work around to get the same effect?

如果我可以使用静态方法,我会将 TargetMethod 设为虚拟,它就可以完成这项工作。但是有没有办法达到同样的效果?

Edit: Yes, I could put a copy of Operation in the child class, but this would require copy and pasting a large bit of code into every child, which in my case is about 35 classes, a maintenance nightmare.

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

采纳答案by Stefan Steinegger

No, you cannot override a static method. "static" also means that it is statically bound by the compiler, so the actual method to be called is not found at runtime, but bound at compile time.

不,您不能覆盖静态方法。“静态”也意味着它是由编译器静态绑定的,因此实际要调用的方法不是在运行时找到的,而是在编译时绑定的。

What you should do is make the class non-static. Make the method virtual and override it and make full benefit of real inheritance. Then, if you really need it, make a static entry point to a reference of your class. For instance a static factory, singleton (it's an anti-pattern in most of the cases but is as good as a static class) or just a static property.

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

回答by Mark Brackett

You could store the TargetMethod as a delegate, which a subclass could change as needed:

您可以将 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");
       });
    }
}

Since these are static instances, though - the _targetMethodis shared across all instances - changing it in TestChildchanges it for TestBaseas well. You may or may not care about that. If you do, generics or a Dictionary<Type, Action>might help.

但是,由于这些是静态实例 -_targetMethod在所有实例之间共享 - 更改它TestChild也会更改它TestBase。你可能关心也可能不关心。如果你这样做,泛型或 aDictionary<Type, Action>可能会有所帮助。

Overall, though, you'd have a much easier time if you didn't insist on statics, or perhaps used composition instead of inheritance.

但是,总的来说,如果您不坚持使用静态,或者使用组合而不是继承,那么您的时间会容易得多。

回答by Nick Whaley

If you are looking to do abstract static methods, then this works, and turns out to be the easiest solution for me to adapt to:

如果您正在寻找抽象静态方法,那么这很有效,并且证明是我适应的最简单的解决方案:

class TestBase<ChildType> where ChildType : TestBase<ChildType> {
    //public static abstract void TargetMethod();

    public static void Operation() {
        typeof(ChildType).GetMethod("TargetMethod").Invoke(null, null);
    }
}

class TestChild : TestBase<TestChild> {
    public static void TargetMethod() {
        Console.WriteLine("Child class");
    }
}

But I am still marking Stafan as the solution because using instance inheritance is probably the best recommendation for anyone in a similar situation. But I simply would have to rewrite too much code for it.

但我仍然将 Stafan 标记为解决方案,因为对于处于类似情况的任何人来说,使用实例继承可能是最好的建议。但我只需要为它重写太多代码。

回答by Jason D

Ok here is what I have done

好的,这是我所做的

public abstract class Base<T>
    where T : Base<T>, new()
{
    #region Singleton Instance
    //This is to mimic static implementation of non instance specific methods
    private static object lockobj = new Object();
    private static T _Instance;
    public static T Instance
    {
        get
        {
            if (_Instance == null)
            {
                lock (lockobj)
                {
                    if (_Instance == null)
                    {
                        _Instance = new T();
                    }

                }
            }
            return _Instance;
        }
    }

    #endregion //Singleton Instance

    #region Abstract Definitions

    public abstract T GetByID(long id);
    public abstract T Fill(SqlDataReader sr);

    #endregion //Abstract Definitions
}

public class InstanceClass : Base<InstanceClass>
{
    //empty constructor to ensure you just get the method definitions without any
    //additional code executing
    public InstanceClass() { }


    #region Base Methods

    public override InstanceClass GetByID(long id)
    {
        SqlDataReader sr = DA.GetData("select * from table");
        return InstanceClass.Instance.Fill(sr);
    }

    internal override InstanceClass Fill(SqlDataReader sr)
    {
         InstanceClass returnVal = new InstanceClass();
         returnVal.property = sr["column1"];
         return returnVal;
    }
}

I think this will be a viable solution for what you want to do without breaking too many purist OO principles.

我认为这将是您想要做的事情的可行解决方案,而不会破坏太多纯粹的 OO 原则。