2014-03-05 8 views
5

ich auf einige Code arbeite, die so etwas wie dieses:Statische Variableninitialisierung mit neuen gibt einen Code Gefahr

class A 
{ 
    static SomeClass a = new Someclass("asfae"); 
} 

Someclass enthält die erforderliche Konstruktor. Der Code für diese kompiliert ohne Warnung. Aber ich einen Code Gefahr im System zu erhalten:

„Die Someclass Ctor wurde von statischem Konstruktor aufgerufen und/oder statische initialiser“

Dieser Code Gefahren Teil des Systems nur um es besser zu machen, indem Warnung vor möglichen Fehlern im System oder wenn das System dadurch in einen schlechten Zustand geraten kann. Ich habe irgendwo im Web gelesen, dass der statische Konstruktor/Initialisierer in C# in einen Deadlock geraten kann, wenn er darauf wartet, dass ein Thread beendet wird. Hat das etwas damit zu tun?

Ich muss diese Warnung loswerden, wie kann ich das tun. Ich kann das Mitglied nicht statisch machen, da es von einer statischen Funktion verwendet wird. Was soll ich in diesem Fall tun, Brauche Hilfe.

+0

Was ist der Zweck dieses statischen Feldes? – Alex

Antwort

1

Sie können es hinter einer Eigenschaft verstecken und bei der ersten Verwendung initialisieren (nicht Thread-sicher);

class A 
{ 
    static SomeClass aField; 

    static SomeClass aProperty 
    { 
     get 
     { 
      if (aField == null) { aField = new Someclass("asfae"); } 
      return aField; 
     } 
    } 
} 

oder benutzen Faul (thread-safe):

class A 
{ 
    static Lazy<SomeClass> a = new Lazy<SomeClass>(() => new Someclass("asfae")); 
} 

... oder diese sehr ausführliche Thread-sicher-Version :)

class A 
{ 
    static SomeClass aField; 

    static object aFieldLock = new object(); 

    static SomeClass aProperty 
    { 
     get 
     { 
      lock (aFieldLock) 
      { 
       if (aField == null) { aField = new Someclass("asfae"); } 
       return aField; 
      } 
     } 
    } 
} 
+0

mit .net3.5 Lazy wird nicht unterstützt und möchte keine nicht thread-sichere Lösung. – grv

0

Durch sie als statisches Feld Initialisierung, Es verhält sich wie in einem statischen Konstruktor, dh es wird wahrscheinlich initialisiert, wenn eine Instanz Ihrer Klasse zum ersten Mal instanziiert wird, könnte aber früher passieren. Wenn Sie über genau einstellen wollen, wenn das Feld initialisiert wird, könnten Sie Lazy<T> verwenden, zB:

{ 
    static Lazy<SomeClass> a = new Lazy<SomeClass>(() => new Someclass("asfae")); 
} 

Auf diese Weise wissen Sie, dass die Initialisierung von Someclass wird nur das erste Mal passiert das Feld zugegriffen wird und seine Value Eigenschaft genannt.

0

Ich denke, Ihr Problem verstehen Sie den Unterschied zwischen statischen Konstruktoren und Typ initializers wissen müssen, gibt es einen großen Artikel von Jon Skeet zu diesem Problem:

http://csharpindepth.com/Articles/General/Beforefieldinit.aspx

Der Punkt ist, dass folgende Konstruktionen sind nicht die gleichen, und es gibt Unterschied im Verhalten:

class Test 
{ 
    static object o = new object(); 
} 

class Test 
{ 
    static object o; 

    static Test() 
    { 
     o = new object(); 
    } 
} 

in jedem Fall können Sie versuchen, einen statischen Konstruktor erstellen für Ihre Klasse mehr Kontrolle zu haben, auf th der Lage sein, ist die Initialisierung, und vielleicht wird die Warnung verschwinden.

Wenn das Mitglied nur von einer statischen Methode verwendet wird, und nur von diesem, würde ich empfehlen, Sie in den Gültigkeitsbereich dieser statischen Methode und nicht als Mitglied der Klasse.

+0

Das Element wird von anderen Methoden verwendet, von denen einige nicht statisch sind. – grv

+0

@grv in diesem Fall können Sie nur die Lazy-Klasse verwenden (ich benutze sie auch oft) oder den statischen Konstruktor, der schneller und auch ziemlich sicher und Threading-sicher ist. – Rafa

+0

Ich benutze .net 3.5 so mit faul ist keine Option, da es nicht unterstützt wird und ich versuchte statische Konstruktor und ich bekomme immer noch die Warnung. Irgendeine andere Idee? – grv