2009-04-30 155 views
22

我的代码如下:C#编译器:无法在非静态上下文中访问静态方法

public class Anything 
{ 
    public int Data { get; set;} 
} 

public class MyGenericBase<T> 
{ 
    public void InstanceMethod(T data) 
    { 
     // do some job 
    } 

    public static void StaticMethod(T data) 
    { 
     // do some job 
    } 

    // others members... 
} 

public sealed class UsefulController : MyGenericBase<Anything> 
{ 
    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(); 
     c.B.InstanceMethod(null); // Works as expected. 
     c.B.StaticMethod(null);  // Doesn't work. 
            // Static method call on object rather than type. 
            // How to get the static method on the base type ? 
     c.B.ProxyToStaticMethod(); // Works as expected. 
    } 
} 

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

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

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

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

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

感谢您的投入!


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

 public class GenericBase<T> : MyGenericBase<T> 
{ 
    // Create instance calls here for every base static method. 
} 

public sealed class UsefulController : GenericBase<Anything> 
{ 
    // others non derived members... 
} 

回答

26

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

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

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

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

+0

非常具有启发性,谢谢!阅读下面的答案,我想知道一个可能的解决方案。随意发表评论。 – 2009-04-30 23:42:08

+0

毕竟,他们不称为静态 – BlackTigerX 2009-04-30 23:58:26

2

你不能在C#中做到这一点。你可以在VB.NET和Java中使用它,但说实话,这并不合理。它只是给你一个static方法中的多态性的错觉,这种方法并不是真实的。由于它不是多态的,整个方法调用在编译时是已知的(静态的),你可以直接用类名来提及调用。

9

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

MyGenericBase<Anything>.StaticMethod(null); 
+0

谢谢!我已经注意到这一点。我正在寻找一种方法来通过容器进行这些调用。您认为如何首先将基类派生到另一个基类,这个基类将包含对静态方法的实例调用,然后从中派生出来? – 2009-04-30 23:38:53

1

你可以做其中的一个:

UsefulController.StaticMethod(null); 
MyGenericBase<Anything>.StaticMethod(null); 

使用实例是不可能的,因为别人已经发表过解释。

+0

谢谢!我已经注意到这一点。我正在寻找一种方法来通过容器进行这些调用。您认为如何首先将基类派生到另一个基类,这个基类将包含对静态方法的实例调用,然后从中派生出来? – 2009-04-30 23:38:32

+0

如果你认为你“需要”这个实例调用,只需添加你的代理方法。我的建议只是试图保持API清洁和明确。 – Lucero 2009-05-01 00:19:57

+0

因为我不能直接使用包含类来调用静态成员,所以它似乎是目前唯一的解决方案。我同意尽可能保持API的清洁。 – 2009-05-01 00:23:53

相关问题