C#:如何从派生类的静态方法调用基类的静态方法?

在C#中,我有基类Product和派生类Widget。

产品包含一个静态方法MyMethod()。

我想从静态方法Widget.MyMethod()调用静态方法Product.MyMethod()。

我不能使用base关键字,因为它只适用于实例方法。

我可以显式地调用Product.MyMethod(),但是如果我稍后将Widget更改为从另一个类派生,我必须修改该方法。

C#中有一些类似于base的语法允许我从派生类的静态方法中调用基类的静态方法吗?

static方法基本上是一种从面向对象的概念中回退的方法。 因此,它们在inheritance层次结构中不是非常灵活,并且不可能直接执行此类操作。

我能想到的最接近的是using指令。

 using mybaseclass = Namespace.BaseClass; class MyClass : mybaseclass { static void MyMethod() { mybaseclass.BaseStaticMethod(); } } 

它可以做到,但我不推荐它。

 public class Parent1 { public static void Foo() { Console.WriteLine("Parent1"); } } public class Child : Parent1 { public new static void Foo() { Type parent = typeof(Child).BaseType; MethodInfo[] methods = parent.GetMethods(); MethodInfo foo = methods.First(m => m.Name == "Foo"); foo.Invoke(null, null); } } 

使用reflection调用静态方法与调用实例方法完全相同,只是为实例传递null。 你需要FlattenHierarchy,因为它是在祖先中定义的。

 var type = assy.GetType("MyNamespace.MyType"); MethodInfo mi = type.GetMethod("MyStaticMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy); mi.Invoke(null, null); 

进一步的阅读和思考让我和其他人一样回答问题:为什么要使用这样的静态方法? 您是否正在尝试进行函数式编程,如果是这样,为什么不使用lambda表达式呢? 如果您希望多态行为具有共享状态,则实例方法会更好。

可以办到:

 public class Parent1 { protected static void Foo() { Console.WriteLine("Parent1"); } } public class Child : Parent1 { public static void Foo() { return Parent1.Foo(); } } 

可用于unit testing受保护的静态方法(例如)。

首先,如果你担心重新养育一个类,那么你可能做错了inheritance。 inheritance应该用于建立“is-a”关系,而不仅仅是促进代码重用。 如果您需要单独重用代码,请考虑使用委托,而不是inheritance。 我想你可以在子类型和它的父类之间引入一个中间类型,但我会让这种可能性驱动我的设计。

其次,如果您需要使用基类中的function但是扩展它并且用例需要静态方法,那么您可能需要考虑使用一些外部类来保存function。 我心目中的经典案例是工厂模式。 实现Factory模式的一种方法是通过Factory Methods,一个构造该类实例的类的静态方法。 通常构造函数是受保护的,因此工厂方法是从外部构建类的唯一方法。

在inheritance层次结构中使用工厂方法重用的一种方法是将公共代码放在受保护的方法中,并从工厂方法调用该方法,而不是直接从子类型工厂方法调用基类工厂方法。 更好的实现可能使用相同的技术,但将Factory方法移动到Factory类并使用构造函数逻辑(内部现在,而不是私有),可能与初始化方法结合使用,以创建对象。 如果您inheritance的行为是来自类的外部(decryption / validation / etc),则可以使用Factory中的共享方法(或组合)来允许在Factory方法之间重用。

如果不了解使用静态方法的目标,很难给出确切的方向,但希望这会有所帮助。

静态方法不是多态的,所以你想要做的是不可能的。

试图找到一种将静态方法视为多态的方法是可能的但很危险,因为语言本身并不支持它。

一些建议:

  • reflection
  • 别名基类(例如Mehrdad的例子 )

考虑到静态方法不会在实例数据中中继…你应该有一个静态的“MyMethod”,它根据参数或类似的东西表现不同。

请记住,在一个类中定义的静态方法只是一种对代码进行排序的方法……但是如果将该方法放在其他地方它也是一样的…因为它不会在放置它的对象上进行中继。

编辑:我认为你最好的选择是明确地使用Product.MyMethod …如果你认为……你的Widget可能不会改变它的基础…而且在这种情况下它是一个小的改变在代码中。

静态方法是“类级”方法。 它们旨在成为适用于特定类的所有实例的方法。 因此,这种方法的inheritance没有意义,因为它会改变应用于类实例的含义。 例如,如果您循环遍历产品集合(某些Widget,某些不是)并在每个产品上调用MyMethod,则调用的方法将由类的实例确定。 这违反了静态方法的目的。

你可以通过简单地完全不使用静态方法来做你想要更干净的事情,因为在你的例子中,似乎MyMethod并不适用于所有的Product实例。 但是,您可以通过使用“IMyMethod”之类的接口类来实现与描述相同的效果。 这种方法仍然没有使用静态方法。 我想我没有看到需要静态方法。 为什么要使用静态方法开始?

这很简单。 比使用别名,reflection等简单得多。也许在新增的.NET,IDK中它变得更容易了,但这非常好用。 就像实例方法一样,访问基本方法不需要使用base ,它是可选的,通常在inheritance和基类具有相同名称的方法时是必需的。 即使没有base关键字,您也可以访问基类的静态方法,就像它们在您调用的类中一样。 我只在从派生类的静态方法调用基本静态方法时测试了这个。 如果从实例方法调用静态方法,则可能无法工作。

 public class BaseThings { protected static void AssertPermissions() { //something } } public class Person:BaseThings { public static void ValidatePerson(Person person) { //just call the base static method as if it were in this class. AssertPermissions(); } }