2012-02-22 11 views
79
namespace MyNameSpace 
{ 
    static class MyClass 
    { 
     static MyClass() 
     { 
      //Authentication process.. User needs to enter password 
     } 

     public static void MyMethod() 
     { 
      //Depends on successful completion of constructor 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyClass.MyMethod(); 
     } 
    } 
} 

Ecco la sequenza che ho assuntoCome funziona un costruttore statico?

  1. Inizio del costruttore statico
  2. Fine del costruttore statico
  3. Inizio principale
  4. Inizio MyMethod
  5. Fine principale

Ora in qualsiasi scenario se 4 inizierà prima delle 2, sono fregato. È possibile?

+8

Questa è una domanda java o C#? Hai inserito entrambi i tag e non penso che le specifiche siano le stesse nelle due lingue. – ARRG

+0

Nella mia apertura questo è lo stesso per entrambi .. Ma io sono C# guy .. Sry per quello – om471987

+4

Java non ha un costruttore statico allo stesso modo, solo blocchi statici per l'inizializzazione statica. static {// do something ...} – deraj

risposta

214

lei ha chiesto solo una domanda qui, ma ci sono una dozzina di domande che si dovrebbe hanno chiesto, quindi mi limiterò a tutti rispondono.

Ecco la sequenza che ho assunto

  1. Inizio del costruttore di classe (anche conosciuto come cctor)
  2. Fine cctor
  3. inizio principale
  4. inizio MyMethod

È corretto?

No. La sequenza corretta è:

  1. Inizio cctor per il programma, se ce n'è uno. Non c'è.
  2. Fine del cctor per Programma, se ce n'è uno. Non c'è.
  3. Inizio di Main
  4. Inizio cctor per MyClass
  5. Fine cctor per MyClass
  6. Inizio MyClass.MyMethod

Che cosa succede se c'è un campo inizializzatore statico?

Il CLR è autorizzato a modificare l'ordine di esecuzione degli inizializzatori del campo statico in alcuni casi. Vedere pagina di Jon sul tema per i dettagli:

The differences between static constructors and type initializers

E 'mai possibile che un metodo statico come MyMethod di essere chiamato prima della cctor di quella classe completa?

Sì.Se il cctor stesso chiama MyMethod, ovviamente MyMethod verrà chiamato prima del completamento del cctor.

Il cctor non chiama MyMethod. È mai possibile chiamare un metodo statico come MyMethod prima che il cctor di MyClass sia completato?

Sì. Se il cctor utilizza un altro tipo il cui cctor chiama MyMethod, MyMethod verrà chiamato prima del completamento del cctor MyClass.

Nessun cctor chiama MyMethod, direttamente o indirettamente! È mai possibile che un metodo statico come MyMethod venga chiamato prima del completamento del cctor di MyClass?

No.

E 'ancora vero anche se ci sono più thread coinvolti?

Sì. Il cctor finirà su un thread prima che il metodo statico possa essere chiamato su qualsiasi thread.

Il cctor può essere chiamato più di una volta? Supponiamo che due thread causino l'esecuzione del cctor.

Il cctor è garantito per essere chiamato al massimo una volta, indipendentemente dal numero di thread coinvolti. Se due thread chiamano MyMethod "allo stesso tempo", allora corrono. Uno di loro perde la gara e blocca fino a quando il cctor MyClass non completa il thread vincente.

Il filo perdente blocchi fino a quando il cctor è fatto? Davvero?

Davvero.

Che importa se il cctor sul filo vincente chiama il codice che blocca su un blocco precedentemente adottate dal perdendo filo?

Quindi si dispone di una classica condizione di inversione dell'ordine di blocco. Il tuo programma si blocca. Per sempre.

Sembra pericoloso. Come posso evitare lo stallo?

Se fa male quando lo fai allora smettere di farlo. Non fare mai qualcosa che può bloccare in un cctor.

È consigliabile fare affidamento sulla semantica di inizializzazione di cctor per imporre requisiti di sicurezza complessi? Ed è una buona idea avere un cctor che faccia interazioni con l'utente?

Né sono buone idee. Il mio consiglio è che dovresti trovare un modo diverso per garantire che vengano soddisfatte le precondizioni che influenzano la sicurezza dei tuoi metodi.

+4

Eric, sono curioso del perché hai sostituito "costruttore statico" con "costruttore di classi" o "cctor" in questa risposta. È improprio utilizzare "costruttore statico" quando ci si riferisce a un cctor? – phoog

+6

@phoog: volevo essere coerente con il mio uso della terminologia, quindi ho scelto quello più breve. "Static constructor" e "class constructor" vanno bene entrambi. Come dettaglio di implementazione, il costruttore statico di un tipo viene emesso come un metodo speciale chiamato ".cctor", quindi è comune riferirsi a tale costruttore come "a cctor". Se scrivessi in un contesto più formale, userei uno dei termini più lunghi. –

10

Il n. 3 è in realtà il n. 1: l'inizializzazione statica non viene avviata fino al primo utilizzo della classe a cui appartiene.

È possibile se MyMethod viene chiamato dal costruttore statico o da un blocco di inizializzazione statico. Se non invochi MyMethod direttamente o indirettamente dal tuo costruttore statico, dovresti stare bene.

+0

Initialize Proprio come una nota, e 'la mia comprensione che l'inizializzazione 'static' può effettivamente essere chiamato prima del primo utilizzo a seconda dell'idoneità alle ottimizzazioni. –

+0

@JamesMichaelHare secondo MS docs, ["L'esecuzione di un costruttore statico viene attivata dal primo degli eventi seguenti che si verificano all'interno di un dominio dell'applicazione: (1) Viene creata un'istanza della classe. (2) Qualsiasi elemento statico i membri della classe sono referenziati. "] (http://msdn.microsoft.com/en-us/library/aa645612%28v=vs.71%29.aspx) – dasblinkenlight

+1

Per un costruttore statico, true, ma per l'inizializzazione statica era il mio punto. Scusate, forse stavo solo selezionando lendini sulla frase 'l'inizializzazione statica non parte ...' è vero per la costruzione statica, ma non se la classe non ha un costruttore statico, quindi l'inizializzazione statica potrebbe accadere prima. –

22

Secondo la MSDN, un costruttore statico:

Un costruttore statico viene chiamato automaticamente per inizializzare la classe prima della prima istanza viene creata o qualsiasi membri statici sono riferimento.

Così il costruttore statico sarà chiamato prima del metodo statico MyClass.MyMethod() viene richiamato (assumendo non anche invocato durante la costruzione statica o campo di inizializzazione statico naturalmente).

Ora, se si sta facendo qualcosa di asincrono in quello static constructor, allora è il tuo lavoro sincronizzarlo.

+7

Se stai facendo qualcosa di asincrono che coinvolge un secondo thread in un costruttore statico , * ti trovi in ​​un mondo di dolore *. Niente rende i deadlock più veloci. Vedi http://stackoverflow.com/a/8883117/88656 per un esempio. –

+0

@Eric: d'accordo ... Non vorrei farlo, ma non ero sicuro del suo esempio che cosa volesse esattamente essere finito prima che MyMethod venisse chiamato ... –

8

Dal documentation (sottolineatura mia):

Un costruttore statico viene chiamato automaticamente per inizializzare la classe prima della prima istanza è creato o qualsiasi membri statici sono fatto riferimento.

2

si può garantire 4 sarà sempre dopo 2 (se non si crea un'istanza della classe dal metodo statico), ma lo stesso non vale per 1 e 3.

2

La statica il costruttore verrà chiamato prima dell'esecuzione di mymethod. Comunque se sei fregato se 4 è chiamato prima di 2 allora ti suggerisco di ripensare il tuo design. Non dovrebbe comunque fare cose complicate in un costruttore statico.

2

Il CLR garantisce che il costruttore statico venga eseguito prima dell'accesso a qualsiasi membro statico. Tuttavia, il tuo design è un po 'puzzolente. Sarebbe più semplice per fare qualcosa di simile:

static void Main(string[] args) 
{ 
    bool userIsAuthenticated = MyClass.AuthenticateUser(); 
    if (userIsAuthenticated) 
     MyClass.MyMethod(); 
} 

con il vostro disegno, se l'autenticazione non riesce, l'unico modo per impedire MyMethod l'esecuzione è di un'eccezione.

2

È garantito che un costruttore di una classe statica è stato chiamato prima che uno qualsiasi dei suoi metodi venga eseguito. Esempio:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine("Press enter"); 
     Console.ReadLine(); 
     Boop.SayHi(); 
     Boop.SayHi(); 
     Console.ReadLine(); 
    } 

} 

static class Boop 
{ 
    static Boop() 
    { 
     Console.WriteLine("Hi incoming ..."); 
    } 

    public static void SayHi() 
    { 
     Console.WriteLine("Hi there!"); 
    } 
} 

uscita:

Premere Invio

// Dopo aver premuto Invio

Hi arrivo ...

Hi there!

Ciao!

+0

using System; namespace MyNamespace { classe Programma { static void Main (string [] args) { Console.WriteLine ("Iscritta nel main"); Boop.SayHi(); Boop.SayHi(); }} classe statica Boop { statica Boop() { Console.Read(); Console.WriteLine ("Chiave del costruttore inserita"); } vuoto statico pubblico SayHi() { Console.WriteLine ("Il metodo è chiamato"); } } } sì questo programma offre una migliore comprensione – om471987

+0

Possibilmente. La prossima volta postala come risposta, però. È più utile e visibile allora. – haiyyu

0

Oppure si può scorrere nel debugger.

+0

Sì, ero sicuro del percorso felice. Volevo conoscere ogni singola condizione ... – om471987

1

Ecco l'ordine reale in cui le cose vanno giù:

  1. Inizio Main
  2. Inizio della statica MyClass costruttore
  3. Fine della MyClass costruttore statico
  4. Inizio MyMethod
  5. Fine Main