2009-09-14 7 views
7
public class ClassA 
{ 
    public static readonly string processName; 
} 

public class ClassB : ClassA 
{ 
    static ClassB() 
    { 
     processName = "MyProcess.exe"; 
    } 
} 

Ich erhalte einen Fehler beim Kompilieren des obigen C# -Codes.Zuordnung zum statischen schreibgeschützten Feld der Basisklasse

Der Fehler sagt - „Ein statisches Nur-Lese-Feld nicht (außer in einem statischen Konstruktor oder eine Variableninitialisierer) zugeordnet werden kann“

Aber ich es in einem statischen Konstruktor bin zuweisen.

Die Notwendigkeit für eine solche statische Variable besteht darin, dass die Basisklasse über Methoden verfügt, die diese Variable verwenden, die abgeleiteten Klassen und die Basisklasse jedoch unterschiedliche Werte für diese Variable haben müssen. Der Wert ist jedoch für alle Instanzen der jeweiligen Klasse konstant. Es muss nur gelesen werden, weil es nirgends geändert werden darf.

Was ist der Fehler im obigen Code? (Wenn es welche gibt), scheint es mir nicht möglich zu sein. Die Fehlermeldung hilft nicht. Weil ich damit nichts falsch mache.

Wenn ein Fehler auftritt, wie kann ich diese Funktionalität implementieren? Ich weiß, ein einfacher Workaround wäre, es zu einer Instanzvariable zu machen und ihnen unterschiedliche Werte in den abgeleiteten Klassen zuzuweisen. Dies ist jedoch unnötig, da der Wert für alle Instanzen der jeweiligen Klasse konstant ist.

Antwort

14

Sie zuweisen in der falsche statische Konstruktor obwohl. Sie kann nur in einem statischen Konstruktor für den Typ deklariert werden, der die Variable deklariert.

Angenommen, Sie haben eine andere Klasse, die von ClassC abgeleitet ist und dasselbe tut - Sie würden die Variable überschreiben, die nur gelesen werden soll. Es gibt eine einzelne statische Variable hier, jedoch viele abgeleitete Klassen, die Sie haben.

Eine Antwort ist ein statisches Variable zu vermeiden, mit aber eine virtuellen Eigenschaft in der Basisklasse setzen, und jede abgeleitete Klasse macht die Eigenschaft außer Kraft setzen, eine andere Konstante zurückzukehren:

public class ClassA 
{ 
    public virtual string ProcessName { get { return "ClassAProcess"; } } 
} 

public class ClassB : ClassA 
{ 
    public override string ProcessName { get { return "MyProcess.exe"; } } 
} 

Grundsätzlich Option wäre es, die "statischen" Bits in eine separate Hierarchie zu trennen - effektiv klingt es so, als würden Sie Polymorphismus über den Typ anstelle von Instanzen wünschen, und das wird in .NET nicht unterstützt.

+1

Genau! "Polymorphismus über den Typ". Ich denke nicht, dass es passender formuliert werden könnte. Danke für den Hinweis, dass es in .NET nicht unterstützt wird. – Poulo

5

In Ihrem Beispiel existiert nur ein einziges Feld, das der Basisklasse, und Sie können keine unterschiedlichen Werte in einem einzelnen Feld haben. Außerdem können Sie nur readonly Felder in derselben Klasse initialisieren, nicht in abgeleiteten Klassen. Eine Abhilfe könnte eine generische Klasse wird definiert, wie:

static class ProcessNames<T> { 
    public static string Value { get; set; } 
} 

und verwendet ProcessNames<DerivedClassType>.Value statt. Offensichtlich wird der Wert auf diese Weise öffentlich zugänglich sein.

Sie sollten jedoch sehen, ob das Definieren des Felds in jeder abgeleiteten Klasse Ihrem Bedarf entspricht und nur auf Workarounds zurückgreift, wenn dies nicht der Fall ist.

1

Es gibt viele Möglichkeiten, die Katze zu häuten. Hier ist eine andere Möglichkeit, wie Sie es tun können.

public class ClassA 
{ 
    public string ProcessName{ get; private set;} 

    public ClassA() 
    { 
     ProcessName = "ClassAProcess"; 
    } 

    public ClassA(string processName) 
    { 
     ProcessName = processName; 
    } 
} 

public class ClassB : ClassA 
{ 
    public ClassB() : base("ClassAProcess") 
    { 
    } 
} 
+0

aber das funktioniert nur bei Instanzvariablen, was nicht wirklich das erreicht, was man wollte –