C#编译器:无法在非静态上下文中访问静态方法

我有以下代码:

public class Anything { public int Data { get; set;} } public class MyGenericBase { public void InstanceMethod(T data) { // do some job } public static void StaticMethod(T data) { // do some job } // others members... } public sealed class UsefulController : MyGenericBase { public void ProxyToStaticMethod() { StaticMethod(null); } // others non derived members... } public class Container { public UsefulController B { get; set; } } public class Demo { public static void Test() { var c = new Container(); cBInstanceMethod(null); // Works as expected. cBStaticMethod(null); // Doesn't work. // Static method call on object rather than type. // How to get the static method on the base type ? cBProxyToStaticMethod(); // Works as expected. } } 

编译器非常生气……我理解错误信息,但我不知道如何解决这个问题。 我试图获取一个类型而不是一个对象来进行静态方法调用,但我找不到正确的方法。 而且这导致一些不优雅的东西。

基本上,GenericBase是来自具有许多静态方法和一些实例方法的框架的类。 控制器正在键入此类并进行扩展。

容器是一组逻辑相关的控制器。

有趣的事情:这个代码的Java版本正确编译,但有一个警告。 执行也是正确的。

是否存在解决此问题的设计模式?

感谢您的投入!


由于你的答案,我找到了摆脱这个问题的方法。 它似乎有效,但我不知道是否有副作用正确知道。

  public class GenericBase : MyGenericBase { // Create instance calls here for every base static method. } public sealed class UsefulController : GenericBase { // others non derived members... } 

将编译对静态方法的调用以调用特定类的特定静态方法。 换句话说,它不会使用B的内容来确定调用哪个静态方法。

所以调用必须在编译时可以解析,因此它会抱怨,因为它知道所有内容都可以用多种具体类型替换该属性的内容,这意味着必须将对静态方法的调用解析为这两个类中的静态方法。

编译器没有像虚拟或抽象静态方法那样的东西,所以对于一个,你不能保证所有这些类都有静态方法。 因为调用必须在编译时可以解析,所以它不会像那样工作。

正如您所注意到的,您可以调用对象的实例方法,该方法又调用静态方法。 这不会使上述规则无效,因为当编译器编译该实例方法时,它将调用哪个静态方法是常量且已知的。

要调用静态方法,您需要从它定义的类中引用它,而不是该类的实例。

  MyGenericBase.StaticMethod( null ); 

你不能在C#中做到这一点。 你可以用VB.NET和Java做到这一点,但老实说,它并没有真正意义。 它只是在static方法中给你一种错误的多态性,这在任何方面都是不现实的。 由于它不是多态的,整个方法调用在编译时(静态)是已知的,你可以直接用类名来提及调用。

你可以做其中一个:

 UsefulController.StaticMethod(null); MyGenericBase.StaticMethod(null); 

正如其他人已经解释的那样,使用该实例是不可能的。

从9年前开始,我知道这是多年前的事了。 我继续练习C#,没有关心rl的实现。 我认为你的post没有inheritance,OOAD和封装(信息隐藏)的目标。

从你的代码到我的代码。

 public class Anything { private int data, data2; //field public Anything() { data = default(int); } public int Data { get; set; } } public class GenericParentClass { public static void StaticMethod(T data) { // do some job } public void InstanceMethod(T data) { // do some job } } public sealed class UsefulController : GenericParentClass where T : Anything, new() { //all static public methods must be placed before all non-static public methods. [StyleCop Rule: SA1204] public static new void StaticMethod(T data) //'UsefulController'.StaticMethod(Anything) hides inherited member 'GenericParentClass.StaticMethod(Anything)'. Use the new keyword if hiding was intended. { GenericParentClass.StaticMethod(data); //'data' is a variable but used like a type //arugement type T is not assignable to parameter type 'data'. } public void EncapsulatedStaticMethod() { T @class = new T(); //cannot create an instance of the variable type T because it does not have the new() constraint. //T is type and @class is variable and new is an instance. StaticMethod(@class); } public void EncapsulatedInstanceMethod(T data) { base.InstanceMethod(data); } } public class Container { public UsefulController B { get; set; } } public class Testing { public static void Main() { Anything @var = new Anything(); var c = new Container(); cBInstanceMethod(null); cBEncapsulatedStaticMethod(); cBEncapsulatedInstanceMethod(var); } }