2014-01-31 92 views
1

在我的許多嘗試中找到一個很好的解決方案在C#中的靜態覆蓋(在Objective-C中很容易,所以不要告訴我「這是不可能的」,或者說「只有對象是多態的「,因爲我知道)我試着用代表的方法。我的代碼是:靜態代理和覆蓋

public class Animal 
{ 
    public static Func<string> Name { get; protected set; } 

    static Animal() 
    { 
     Name =() => "Animal"; 
    } 
} 

public class Cat : Animal 
{ 
    static Cat() 
    { 
     Name =() => "Cat"; 
    } 
} 

但是當我打電話Cat.Name()我仍然得到「動物」。我不是在尋求解決方案,我問:爲什麼?

+1

1)字段'Animal.Name'只有一個實例。沒有單獨的「Cat.Name」。 'Cat.Name'和'Animal.Name'將總是返回相同的值,Cat或者Animal取決於哪個靜態構造函數是最近運行的。 2)靜態構造函數還沒有運行,所以它仍然返回舊名稱。靜態構造函數只有在訪問Cat的成員(或構造它的一個實例)時纔會運行,即使通過Cat來訪問,也不會生成Animal.Name。 – CodesInChaos

+1

我會用反射和泛型的混合來解決你最初的問題。泛型類將爲每種類型都有一個獨特的靜態字段。 – CodesInChaos

+0

這是一個好主意,你建議用類似「動物」,「動物」,......來代替一個課程方案嗎? – Gerard

回答

1
  1. 該字段只有一個實例Animal.Name。沒有單獨的Cat.Name

    這意味着Cat.NameAnimal.Name總是返回相同的值,無論是CatAnimal取決於哪個靜態構造函數是最近期的運行。

  2. 靜態構造函數尚未運行,所以它仍然返回舊名稱。靜態構造函數只在訪問Cat的靜態成員(或構造它的一個實例)時運行。 Cat.Name從這個意義上說不是Cat的成員,因爲它實際上是Animal.Name

    規格說,關於何時執行靜態構造函數:

    對於封閉類類型的靜態構造函數在給定的應用程序域中執行最多一次。靜態構造的執行由第一以下事件觸發的應用程序域內發生:
    ·創建類型的一個實例。
    ·引用了類類型的任何靜態成員。

1

沒有在.NET靜態方法的繼承。就IL而言,Cat.Name不存在,但.NET允許您從子類調用基類的方法。這解釋了爲什麼永遠不會調用靜態Cat構造函數。

作爲NameAnimal貓不的方法,Animal.Name被觸發,因此,Animal's構造將會運行。結果是:你是一隻動物,而不是一隻貓。

.NET Static Constructors on MSDN