2009-12-03 2 views
5

Sans aucun code dans les sous-classes, j'aimerais qu'une classe abstraite ait une copie différente d'une variable statique pour chaque sous-classe. En C#Faire une superclasse a une variable statique qui est différente pour chaque sous-classe dans C#

abstract class ClassA 
{ 
    static string theValue; 

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

et (par exemple):

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

Ma solution actuelle est la suivante:

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

Bien que cela fonctionne bien, je me demande s'il y a un plus élégant ou façon intégrée de le faire?

Ceci est similaire à Can I have different copies of a static variable for each different type of inheriting class, mais je n'ai aucun contrôle sur les sous-classes

+0

Vous pourriez probablement le faire en piratant un 'Dictionary ' et en appelant 'GetType()', mais ce serait horrible ... –

+0

Pour que les membres statiques virtuels/abstraits seraient bien. voir (recherche de "membre statique virtuel") – VolkerK

+0

pourquoi ne pas le rendre NON statique? – BlackTigerX

Répondre

5

Bien que cela fonctionne bien, je me demande s'il y a une façon plus élégante ou intégrée de le faire?

Il n'y a pas vraiment de façon intégrée de le faire, car vous êtes en quelque sorte en train de violer les principes de base de l'OO. Votre classe de base ne devrait avoir aucune connaissance des sous-classes dans la théorie orientée objet traditionnelle. Cela étant dit, si vous devez le faire, votre implémentation est probablement aussi bonne que vous l'obtiendrez, sauf si vous pouvez ajouter directement d'autres informations aux sous-classes. Si vous avez besoin de contrôler cela, et vous ne pouvez pas changer de sous-classes, ce sera probablement votre meilleure approche.

0

Il y a une solution de rechange qui pourrait ou ne pourrait pas être meilleur que le vôtre, selon le cas d'utilisation:

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

Cette approche est utilisée dans EqualityComparer<T>.Default. Bien sûr, il n'est pas utilisé pour ce problème. Vous devriez vraiment envisager de faire GetValue abstrait et le remplacer dans chaque classe dérivée.

+0

Il a mentionné qu'il ne peut pas remplacer GetValue dans chaque classe dérivée ... – enorl76

+0

@ enorl76 Cette question est très ancienne, donc je ne me souviens pas du contexte réel, mais je ne pense pas que cette approche nécessite de surcharger GetValue. La dernière phrase de ma réponse est juste un commentaire sur la bonne approche, pas sur la solution. –

1

Ceci est un peu différent de ce que vous demandez, mais peut-être accomplit la même chose.

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

C'est l'évidence + meilleure façon - malheureusement je ne peux pas modifier les classes B & C – ste

1

Que pensez-vous de cela?



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

Cela fonctionne pour moi. Serait encore plus agréable avec Interface.

+0

soin d'expliquer ce qui est le code fait pour le bénéfice des autres, une décharge de code sans explication ne satisfera pas les utilisateurs SO :) – t0mm13b

+3

Non, cela jamais travailler. Selon le moment où la machine virtuelle voit les types, c'est quand le constructeur statique serait appelé, et donc « myVariable » contiendra la valeur de la dernière ran-statique constructeur. Et pire encore, ce sera une période indéterminée qui que le dernier constructeur sera. – enorl76

Questions connexes