2013-03-14 37 views
1

我需要在C#靜態抽象方法的替代:C#:以所需的*靜態基類方法存根*在所有派生類實施

// fantasy code 
abstract public class BaseClass 
{ 
    static abstract public void RequiredStaticMethod(); 
} 

我只有兩個條件爲RequiredStaticMethod

  1. 所有派生類必須實現它(如編譯器強制執行)。
  2. 它必須沒有類的實例可用;即DerivedClass.RequiredStaticMethod()必須工作。

達到此目的的最佳方法是什麼?

+0

難道你不能使用[接口](http://msdn.microsoft.com/en-us/library/87d83y5b(v = vs.80).aspx)? – MyCodeSucks 2013-03-14 16:13:07

+2

這在C#中不受支持。它已被討論[這裏](http://stackoverflow.com/questions/1380087/whats-the-correct-alternative-to-static-method-inheritance-c)和[這裏](http://stackoverflow.com/questions/774181/why-cant-i-inherit-static-classes) – oleksii 2013-03-14 16:14:26

+0

此問題類似於http://stackoverflow.com/questions/763344/c-sharp-virtual-or-abstract-static-methods/763364 #763364 – 2013-03-14 16:17:34

回答

1

你不能在C#中做到這一點。相反,它可以幫助你用一個抽象的實例方法和Singleton模式:

abstract public class BaseClass 
{ 
    abstract public void RequiredStaticMethod(); 
} 

sealed class Subclass : BaseClass 
{ 
    public static readonly Subclass Instance = new Subclass(); 

    public void RequiredStaticMethod() {}  
} 

您可能要添加你想達到的根本問題的進一步描述。一般來說,您可以使用抽象類來將消費者從實際實現中解耦出來,方法是使用抽象類型來代替。但是,這顯然不能用靜態成員來完成。正如Jon所評論的那樣,我看不到你打算如何消耗BaseClass

你也許也可以使用一個接口,並通過反射找到所有實現類型。這將產生一個IFoo輸入迭代並調用你的方法在一個實例綁定的方式:

class Program 
{ 
    public static void Main() 
    { 
     var classes = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.GetInterface("IFoo") != null); 
     foreach(var foo in classes.Select(c => Activator.CreateInstance(c)).Cast<IFoo>()) 
     { 
      foo.RequiredNonStaticMethod(); 
     } 
    } 
} 

public interface IFoo 
{ 
    void RequiredNonStaticMethod(); 
} 

public class FooImpl : IFoo 
{ 
    public void RequiredNonStaticMethod() 
    { 
     Console.WriteLine("Foo"); 
    } 
} 
+0

感謝您的意見:我打算使用反射來調用派生類上的靜態成員。我真的想要一種確保他們始終在那裏的手段;因此在我原來的問題編譯時檢查條件。不過,我可以看到,我需要考慮這一點。 – 2013-03-14 16:38:23

+0

這只是把「每個具體類應該公開一個靜態方法」的問題放到「每個具體類應該暴露一個靜態字段或屬性與相關實例」的問題上 - 同時增加限制,即使它是一個單例也是合理的。考慮到仍然存在編譯器無法驗證的條件,並且仍然需要通過反射來查找事情,所以我寧願不要求單例部分,然後返回到「未編譯時檢查」的方法「一點。 – 2013-03-14 17:12:31

+0

@JonSkeet你說得對,我也喜歡你的思考+單元測試 - 我也不完全滿意我的提議。我仍然在想埃德的問題是否也可以通過使用靜態方法或單例實現單個實例來解決,而不是通過使用C#的編譯時功能來解決。例如,我的第二個選擇不使用單身。但是,它需要無參數的構造函數,這也是不理想的。 – 2013-03-14 18:03:59

3

有什麼可以做的編譯時來驗證它。但是如果你打算用反射調用方法(所以它不像你需要任何形式的多態性),你可以只需文檔每個具體的派生類必須實現一個特定的方法,然後編寫一個單元測試,彙編所有派生類型並檢查它們是否符合要求。

它不像編譯時檢查那麼好,但假設你控制了所有相關的程序集,並且假設你已經足夠頻繁地運行單元測試,它應該是合理無痛的。

+0

感謝喬恩:值得了解。 – 2013-03-14 16:35:30

相關問題