2009-04-30 140 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

相關問題