2009-12-03 4 views
5

Senza alcun codice nelle sottoclassi, vorrei che una classe astratta avesse una copia diversa di una variabile statica per ogni sottoclasse. In C#Fare una superclasse ha una variabile statica diversa per ogni sottoclasse in C#

abstract class ClassA 
{ 
    static string theValue; 

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

e (per esempio):

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

mia soluzione attuale è questa:

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

Anche se questo funziona bene, mi chiedo se c'è un più elegante o modo integrato di farlo?

Questo è simile a Can I have different copies of a static variable for each different type of inheriting class, ma non ho alcun controllo su sottoclassi

+0

Probabilmente si potrebbe fare hacking un 'dizionario ' e chiamando 'GetType()', ma sarebbe orribile ... –

+0

Per quel membro statico virtuale/astratto sarebbe bello. vedi (cerca "membro statico virtuale") – VolkerK

+0

perché non renderlo NON statico? – BlackTigerX

risposta

5

Anche se questo funziona bene, mi chiedo se c'è un modo più elegante o built-in di fare questo?

Non c'è davvero un modo integrato per farlo, poiché stai violando i principi OO di base qui. La tua classe base non dovrebbe avere alcuna conoscenza delle sottoclassi nella teoria tradizionale orientata agli oggetti.

Detto questo, se si deve fare questo, la vostra implementazione è probabilmente tanto buona quanto si otterrà, a meno che non sia possibile aggiungere direttamente altre informazioni alle sottoclassi. Se devi controllarlo e non puoi cambiare sottoclassi, questo sarà probabilmente il tuo approccio migliore.

0

C'è una soluzione alternativa che potrebbe o non potrebbe essere migliore della tua, a seconda del caso d'uso:

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); 
    } 
} 

Questo approccio è utilizzato in EqualityComparer<T>.Default. Certo, non è usato per questo problema. Dovresti davvero considerare di creare GetValue astratto e sovrascriverlo in ogni classe derivata.

+0

Ha detto che non può ignorare GetValue in ogni classe derivata ... – enorl76

+0

@ enorl76 Questa domanda è molto vecchia quindi non ricordo il contesto attuale, ma non penso che questo approccio richieda l'override di GetValue. La frase finale della mia risposta è solo un commento sull'approccio giusto, non parte della soluzione. –

1

Questo è un po 'diverso da quello che stai chiedendo, ma forse realizza la stessa cosa.

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

Questo è l'ovvio + modo migliore - sfortunatamente non riesco a modificare le classi B & C – ste

1

Che dire di questo?



    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"; 
    } 
    } 

Funziona per me. Sarebbe ancora più bello con Interface.

+0

Cura di spiegare cosa sta facendo il codice per il beneficio degli altri, un dump del codice senza spiegazione non soddisferà gli utenti SO :) – t0mm13b

+3

No, questo sarebbe mai lavorare A seconda di quando la VM vede i tipi, questo è il momento in cui verrà chiamato il costruttore statico e quindi 'myVariable' conterrà il valore del costruttore dell'ultimo-run-static. E ancora peggio, sarà indeterminato chi sarà l'ultimo costruttore. – enorl76