2009-12-03 47 views
5

在子類中沒有任何代碼,我希望抽象類爲每個子類都有一個不同的靜態變量副本。在C#製作一個超類有一個靜態變量,每個子類都有不同的c#

abstract class ClassA 
{ 
    static string theValue; 

    // just to demonstrate 
    public string GetValue() 
    { 
     return theValue; 
    } 
    ... 
} 
class ClassB : ClassA { } 
class ClassC : ClassA { } 

和(例如):

(new ClassB()).GetValue(); // returns "Banana" 
(new ClassC()).GetValue(); // returns "Coconut" 

我目前的解決辦法是這樣的:

abstract class ClassA 
{ 
    static Dictionary<Type, string> theValue; 
    public string GetValue() 
    { 
     return theValue[this.GetType()]; 
    } 
    ... 
} 

雖然這工作得很好,我不知道是否有一個更優雅或內置的方式做到這一點?

這類似於Can I have different copies of a static variable for each different type of inheriting class,但我有過亞

+0

你也許可以通過破解一個'Dictionary '來調用'GetType()',但這太可怕了...... – 2009-12-03 21:46:58

+0

對於那個虛擬/抽象的靜態成員來說會很好。請參見(搜索「虛擬靜態成員」) – VolkerK 2009-12-03 21:59:59

+0

爲什麼不只是讓它不是靜態的? – BlackTigerX 2009-12-03 22:01:00

回答

5

雖然這工作得很好沒有控制,我不知道是否有這樣做的更優雅或內置的方式嗎?

這樣做並不是真正的內置方式,因爲您在這裏違反了基本的OO原則。你的基類在傳統的面向對象理論中應該沒有關於子類的知識。這就是說,如果你必須這樣做,你的實現可能與你將要獲得的一樣好,除非你可以直接給子類添加一些其他信息。如果你需要控制這個,你不能改變子類,這可能是你最好的方法。

0

這裏有一個替代的解決方案可能是也可能不是比你的好,根據不同的使用情況:

abstract class ClassA 
{ 
    private static class InternalClass<T> { 
     public static string Value; 
    } 
    public string GetValue() 
    { 
     return (string)typeof(InternalClass<>) 
       .MakeGenericType(GetType()) 
       .GetField("Value", BindingFlags.Public | BindingFlags.Static) 
       .GetValue(null); 
    } 
} 

這種方法在EqualityComparer<T>.Default使用。當然,這不是用於這個問題。你應該考慮在每個派生類中使用GetValue抽象並覆蓋它。

+0

他提到他無法在每個派生類中重寫GetValue ... – enorl76 2013-02-26 04:07:38

+0

@ enorl76這個問題很舊,所以我不記得實際的上下文,但我不認爲這種方法需要重寫GetValue。我的答案的最後一句話只是對正確方法的評論,而不是解決方案的一部分。 – 2013-02-26 05:54:32

1

這與你所要求的有點不同,但也許完成了同樣的事情。

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine((new B()).theValue); 
     Console.WriteLine((new C()).theValue); 
     Console.ReadKey(); 
    } 
} 

public abstract class A 
{ 
    public readonly string theValue; 

    protected A(string s) 
    { 
     theValue = s; 
    } 
} 

public class B : A 
{ 
    public B(): base("Banana") 
    { 
    } 
} 

public class C : A 
{ 
    public C(): base("Coconut") 
    { 
    } 
} 
+0

這是顯而易見的+最好的方式 - 不幸的是我不能改變類B&C – ste 2009-12-03 22:17:36

1

這是怎麼回事?



    class Base { 
    protected static SomeObjectType myVariable; 

    protected void doSomething() 
    { 
    Console.WriteLine(myVariable.SomeProperty); 
    } 
    } 

    class AAA : Base 
    { 
    static AAA() 
    { 
    myVariable = new SomeObjectType(); 
    myVariable.SomeProperty = "A"; 
    } 
    } 

    class BBB : Base 
    { 
    static BBB() 
    { 
    myVariable = new SomeObjectType(); 
    myVariable.SomeProperty = "B"; 
    } 
    } 

它適用於我。 接口會更好。

+0

小心解釋代碼爲別人的利益做什麼,代碼轉儲沒有解釋將不會滿足SO用戶:) – t0mm13b 2012-12-12 00:25:20

+3

不,這將從不工作。根據VM何時看到類型,這是什麼時候將調用靜態構造函數,因此'myVariable'將包含最後一次運行靜態構造函數的值。更糟糕的是,最後一個構造函數的作用是不確定的。 – enorl76 2013-02-26 04:06:08

相關問題