2011-06-28 20 views
5

Ho tre classi, Base, Derived e Final. Derived deriva da Base e Final deriva da Derived. Tutte e tre le classi hanno un costruttore statico. Classe Derived come metodo statico pubblico chiamato Setup. Quando chiamo Final.Setup, mi aspetto che tutti e tre i costruttori statici vengano eseguiti, ma solo quello in Derived viene eseguito.Perché non tutti i costruttori statici chiamati in C# (ad esempio quelli delle classi parent)?

Ecco il codice sorgente di esempio:

abstract class Base 
    { 
     static Base() 
     { 
      System.Console.WriteLine ("Base"); 
     } 
    } 

    abstract class Derived : Base 
    { 
     static Derived() 
     { 
      System.Console.WriteLine ("Derived"); 
     } 

     public static void Setup() 
     { 
      System.Console.WriteLine ("Setup"); 
     } 
    } 

    sealed class Final : Derived 
    { 
     static Final() 
     { 
      System.Console.WriteLine ("Final"); 
     } 
    } 

Questo rende solo parzialmente senso per me. Capisco che chiamare Final.Setup() sia in realtà solo un alias per Derived.Setup(), quindi saltare il costruttore statico in Final sembra abbastanza equo. Tuttavia, perché non viene chiamato il costruttore statico di Base?

Posso risolvere questo problema chiamando un metodo statico non operativo di Base o accedendo a qualche metodo statico fittizio di Base. Ma mi stavo chiedendo: qual è il ragionamento dietro questo comportamento apparentemente strano?

+0

http://msdn.microsoft.com/en-us/library/k9x6w0hc(v=vs.80).aspx – Cipi

+0

Correlati, non un dup: http://stackoverflow.com/questions/6390960/c- costruttore-statico-non-chiamato-da-derivato-classe – Abel

risposta

5

Un costruttore statico viene chiamato quando (secondo TCPL):

  • viene creata un'istanza del tipo di classe.
  • Viene fatto riferimento a qualsiasi membro statico del tipo di classe.

A titolo di esempio, si consideri una classe con il Main metodo statico in cui l'esecuzione inizia così: se si dispone di un costruttore statico, esso sarà chiamato prima si chiama il metodo principale.

Si noti che, anche prima dell'esecuzione di un costruttore statico, qualsiasi campo statico viene inizializzato sul valore predefinito e quindi gli inizializzatori del campo statico vengono eseguiti per quel campo. Solo allora viene eseguito il costruttore statico (cctor).


Per rispondere alla tua domanda in modo più diretto: costruttori statici non sono ereditati, e non può essere chiamato direttamente, quindi il vostro Base cctor non sarà chiamato nel vostro scenario, a meno che non si dà un metodo statico l'astratto Base classe chiamalo per primo, cioè come in Base.Initialize(), come hai già suggerito.

Informazioni sul ragionamento, è semplice, pensante C# (in Java questo è diverso): i metodi statici non sono ereditati, quindi i costruttori statici non dovrebbero essere ereditati in quanto ciò potrebbe causare effetti collaterali indesiderati (un cctor chiamato quando nulla fa riferimento a quella classe).

+0

Grazie per i tuoi chiarimenti. Questo ora ha senso per me. –

0

Le regole C# dettano che i costruttori statici vengono chiamati prima che venga creata la prima istanza della classe o che venga toccato qualsiasi membro statico, ergo, forse mai, come nel tuo caso.

+0

@phresnel: nel mio caso, non creo mai alcun oggetto, solo chiamando 'Derived.Setup()' fa funzionare il costruttore statico su 'Derivato'. Quindi no, i costruttori statici non vengono solo chiamati prima che venga creata un'istanza di una classe. –

+0

@phresnel Non esattamente: "Un costruttore statico viene chiamato automaticamente per inizializzare la classe prima che venga creata la prima istanza o che venga fatto riferimento a qualsiasi membro statico." dal link nel commento. Ciò significa che se accede a qualsiasi cosa in Base, il suo costruttore statico sparerà. –

+0

@Pierre Immagino che il mio commento risponda alla tua domanda. Non fai mai niente con Base, quindi con la regola precedente, il suo costruttore statico non sparerà. –

1

I metodi statici appartengono alla classe e non vi è alcuna ereditarietà. Il fatto che tu possa chiamare Final.Setup è solo uno zucchero sintattico per chiamare Derived.Setup, quindi non è stato fatto riferimento a nessun membro statico di Final - quindi il costruttore statico non viene chiamato. Stessa cosa per la classe Base - non c'è eredità sui membri statici, quindi la classe Base non è coinvolta in alcun modo qui.

Problemi correlati