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

C#虚拟(或抽象)静态方法,c#,inheritance,C#,Inheritance,静态继承的工作原理与实例继承类似。除非不允许将静态方法设置为虚拟或抽象 class Program { static void Main(string[] args) { TestBase.TargetMethod(); TestChild.TargetMethod(); TestBase.Operation(); TestChild.Operation(); } } class TestBase { pu

静态继承的工作原理与实例继承类似。除非不允许将静态方法设置为虚拟或抽象

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");
    }
}
这将输出:

Base class
Child class
Base class
Base class
但我想:

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


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

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


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

您可以将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");
       });
    }
}
由于这些都是静态实例,因此-
\u targetMethod
在所有实例中共享-
TestChild
中更改它也会更改
TestBase
。你可能在乎,也可能不在乎。如果这样做,泛型或
字典可能会有所帮助


不过,总的来说,如果您不坚持静态,或者不使用组合而不是继承,您的工作会轻松得多

如果您希望使用抽象静态方法,那么这是可行的,而且对我来说是最容易适应的解决方案:

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");
    }
}
类TestBase,其中ChildType:TestBase{
//公共静态抽象void TargetMethod();
公共静态无效操作(){
typeof(ChildType).GetMethod(“TargetMethod”).Invoke(null,null);
}
}
类TestChild:TestBase{
公共静态void TargetMethod(){
Console.WriteLine(“子类”);
}
}

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

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;
    }
}
公共抽象类基类
其中T:Base,new()
{
#区域单例实例
//这是为了模拟非实例特定方法的静态实现
私有静态对象lockobj=新对象();
私有静态T_实例;
公共静态T实例
{
得到
{
if(_Instance==null)
{
锁(lockobj)
{
if(_Instance==null)
{
_实例=新的T();
}
}
}
返回_实例;
}
}
#endregion//Singleton实例
#区域抽象定义
公共摘要T GetByID(长id);
公共摘要T填充(SqlDataReader sr);
#endregion//抽象定义
}
公共类InstanceClass:基
{
//空构造函数以确保只获取方法定义,而不包含任何
//执行附加代码
公共InstanceClass(){}
#区域基方法
公共重写InstanceClass GetByID(长id)
{
SqlDataReader sr=DA.GetData(“从表中选择*);
返回InstanceClass.Instance.Fill(sr);
}
内部重写InstanceClass填充(SqlDataReader sr)
{
InstanceClass returnVal=新InstanceClass();
returnVal.property=sr[“column1”];
返回值;
}
}

我认为这将是一个可行的解决方案,可以在不破坏太多纯粹的OO原则的情况下完成您想要做的事情。

为什么要使用静态函数?您将继承与查找和名称隐藏混淆了。可能重复的