2008-10-20 11 views

Répondre

17

Si vous avez un constructeur statique dans votre type, il modifie l'initialisation du type en raison du pas de drapeau beforefieldinit plus appliqué.

Elle affecte également l'ordre d'initialisation - les initialiseurs de variable sont tous exécutés avant le constructeur statique.

C'est à peu près tout ce que je sais.

+3

Pour un exemple concret de pourquoi c'est important: http://stackoverflow.com/questions/217932/whats-the-difference-in-these-ways-of-creating-the-static-instance-for-a-single # 218005 –

+0

De votre lien: 'Le runtime peut décider d'exécuter l'initialiseur de type lors du chargement de l'assembly pour commencer. Je suppose qu'avec les classes génériques ('class Sample ') les règles changent? Avec la résolution à la compilation (par exemple C++), les règles seraient les mêmes, mais .NET effectue une résolution à l'exécution. Le runtime ne sera pas instancié pour chaque combinaison possible, et je doute que lors du chargement de l'assemblage, il regarde vers l'avenir pour voir quels types sont utilisés. –

+0

@NelsonRothermel: Il initialise le type la première fois que le type construit est utilisé - donc si vous utilisez 'Foo ', il l'initialisera ensuite, et relancera l'initialiseur de type si vous utilisez 'Foo '. –

3

Dans ce cas, je ne crois pas qu'il y ait de différence pratique. Si vous avez besoin d'une certaine logique pour initialiser les variables statiques - comme si vous vouliez utiliser différents types concrets d'une interface dans des conditions différentes - vous utiliseriez le constructeur statique. Sinon, l'initialisation en ligne est très bien dans mon livre.

class Foo 
{ 
    private static IBar _bar; 

    static Foo() 
    { 
     if(something) 
     { 
      _bar = new BarA(); 
     } 
     else 
     { 
      _bar = new BarB(); 
     } 
    } 
} 
+0

En fait, il peut faire une grande pratique différence - voir ici (la différence était "fonctionne" vs "ne fait pas"): http://stackoverflow.com/questions/217932/whats-the-difference-in-these-ways-of-creating-the-static -instance-pour-un-single # 218005 –

+0

Je trouve la situat ion décrit là pour être très étrange: | En y réfléchissant, dans mes singletons, j'utilise toujours deux objets statiques, l'instance réelle et un objet à verrouiller. L'instance que je crée toujours dans une méthode de propriété, l'objet de verrouillage que j'instancie en ligne. Je n'y ai jamais pensé auparavant. –

+0

Tobjorn: Cela ressemble à ce que vous faites habituellement quand vous n'en avez pas besoin :) (La plupart du temps, je trouve que les garanties d'initialisation statiques sont parfaitement adéquates pour les singletons.) –

-1

Zone crépusculaire réponse: Il existe une différence d'ordre d'exécution entre les initialiseurs en ligne et l'affectation de ctor ... lorsque vous mélangez des membres statiques et des instances et l'héritage pour démarrer.

For static members, static initializers 
Static ctors (execute bottom up) 
Base static initializer 
Base static ctor and so on 

For instance members, initializers in current class execute first 
Then initializers in base class execute (up the chain) 
Then top-most base ctor is executed (and we walk down now. Instance ctors execute top-down) 
Finally current type's ctor is executed. 

Exemple :)

public class CBase 
    { 
     static Talkative m_Baseob1 = new Talkative("Base Static Initializer-"); 
     static Talkative m_Baseob2; 
     Talkative m_Baseob3 = new Talkative("Base Inst Initializer"); 
     Talkative m_Baseob4; 
     static CBase() 
     { 
      Console.WriteLine("***MethodBegin: Static Base Ctor"); 
      m_Baseob2 = new Talkative("Base Static Ctor"); 
      Console.WriteLine("***MethodEnd: Static Base Ctor"); 
     } 
     public CBase() 
     { 
      Console.WriteLine("***MethodBegin: Instance Base Ctor"); 
      m_Baseob4 = new Talkative("Base Instance Ctor"); 
      Console.WriteLine("***MethodEnd: Instance Base Ctor"); 
     } 
    } 
    public class CDerived : CBase 
    { 
     static Talkative m_ob1 = new Talkative("Derived Static Initializer"); 
     static Talkative m_ob2; 
     Talkative m_ob3 = new Talkative("Derived Inst Initializer"); 
     Talkative m_ob4; 
     static CDerived() 
     { 
      Console.WriteLine("***MethodBegin: Derived Static Ctor"); 
      m_ob2 = new Talkative("Derived Static Ctor"); 
      Console.WriteLine("***MethodEnd: Derived Static Ctor"); 
     } 
     public CDerived() 
     { 
      Console.WriteLine("***MethodBegin: Derived Instance Ctor"); 
      m_ob4 = new Talkative("Derived Instance Ctor"); 
      Console.WriteLine("***MethodEnd: Derived Instance Ctor"); 
     } 
    } 
    internal class Talkative 
    { 
     public Talkative(string sID) 
     { 
      Console.WriteLine(sID + " - Talkative created"); 
     } 
    } 

    # Main function somewhere 
    CDerived s = new CDerived(); 

Sortie:

Derived Static Initializer - Talkative created 

***MethodBegin: Derived Static Ctor 
Derived Static Ctor - Talkative created 
***MethodEnd: Derived Static Ctor 

Derived Inst Initializer - Talkative created 

Base Static Initializer- - Talkative created 

***MethodBegin: Static Base Ctor 
Base Static Ctor - Talkative created 
***MethodEnd: Static Base Ctor 

Base Inst Initializer - Talkative created 

***MethodBegin: Instance Base Ctor 
Base Instance Ctor - Talkative created 
***MethodEnd: Instance Base Ctor 

***MethodBegin: Derived Instance Ctor 
Derived Instance Ctor - Talkative created 
***MethodEnd: Derived Instance Ctor 
+0

Ici, le constructeur statique CBase n'est appelé que parce qu'une instance de CDerived est en cours de construction. Si vous appelez simplement une méthode dans CDerived qui n'a pas besoin de toucher CBase, le constructeur statique de CBase ne sera pas appelé du tout. –

+0

Je serais surpris si c'était le cas .. J'ai mentionné l'héritage dans la première phrase. Mon point: Différence dans la façon dont une variable est initialisée en fonction de comment (initialiseur de champ ou dans ctor), si statique/inst et si elle est dans une hiérarchie de type. mais ouais .. Mon ans est un peu exagéré pour le q de l'OP;) – Gishu