2009-12-17 5 views
0

Récemment, j'ai observé le scénario intéressant suivant dans l'une des applications que je développe en utilisant .NET 3.5. Dans cette application particulaire, j'ai un objet singletion auquel j'accède en tant que variable statique. J'ai exepecté que l'exécution de .NET devrait initialiser cet objet singleton à la première fois que j'y accède, mais il semble que ce n'est pas le cas. Le runtime .NET l'initialise avant que j'accède à cet objet particualr. Voici un code de peudo,Comment le compilateur JIT décide quand initialiser les constructeurs statiques

if(!initSingleton) 
    //Do some work without using the singletion class. 
else 
    //Do some work using the singletion class. 

Même lors de l'exécution de mon code exécute uniquement le code dans le côté le cas d'exécution .NET de l'instruction initialise encore l'objet singleton. Dans certaines applications, je n'ai pas du tout besoin d'accéder à cet objet pariticualr!

Aussi, je ne vois pas ce comportement avec les versions de débogage. Cela semble avoir quelque chose à voir avec les builds optimisés (builds de release).

Est-ce le comportement attendu de l'environnement d'exécution .NET?

Mise à jour:

Voici le code réel,

private void InitServiceClient(NetworkCredential credentials, bool https) 
     { 
      string uri = currentCrawlingWebUrl; 
      if (!uri.EndsWith("/")) 
       uri = string.Concat(uri, "/"); 
      uri = string.Concat(uri, siteDataEndPointSuffix); 

      siteDataService = new SiteData.SiteDataSoapClient(); 
      siteDataService.Endpoint.Address = new EndpointAddress(uri); 

      if (credentials != null) 
      { 
       siteDataService.ClientCredentials.Windows.ClientCredential = credentials; 
      } 
      else if (MOSSStateHandler.Instance.UserName.Length > 0 && MOSSStateHandler.Instance.Password.Length > 0) 
      { 
       siteDataService.ClientCredentials.Windows.ClientCredential.UserName = MOSSStateHandler.Instance.UserName; 
       siteDataService.ClientCredentials.Windows.ClientCredential.Password = MOSSStateHandler.Instance.Password; 
       siteDataService.ClientCredentials.Windows.ClientCredential.Domain = MOSSStateHandler.Instance.Domain; 
      } 

      BasicHttpBinding httpBinding = (BasicHttpBinding)siteDataService.Endpoint.Binding; 
      httpBinding.Security.Mode = (https ? BasicHttpSecurityMode.Transport : BasicHttpSecurityMode.TransportCredentialOnly); 

      string authmode = MOSSConnectorConfiguration.Instance.Config.GetString(ConfigConstants.SHAREPOINT_AUTH_PROVIDER, "ntlm"); 
      if (authmode.Equals("ntlm", StringComparison.OrdinalIgnoreCase)) 
       httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm; 
      else if (authmode.Equals("kerberos", StringComparison.OrdinalIgnoreCase)) 
       httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows; 
      else 
       throw new Exception(string.Format("Not supported")); 
     } 

Même si ma demande n'exécute pas le code dans le côté d'autre si bloquer la classe MOSSStateHandler initialisées.

+0

Pouvez-vous nous expliquer la raison pour laquelle vous devez faire la vérification et où exécutez-vous ce code? C'est très étrange d'avoir à faire ça, ça sent mauvais design. – jmservera

+0

Eh bien, je suis plus intéressé à obtenir une explication sur la façon dont le runtime .NET initialiser les classes statiques. Au-dessus du code est à l'intérieur d'une méthode et en fonction de la valeur de l'indicateur initSingletion je dois maintenir un certain état dans mon application en utilisant cette classe statique. – Shamika

+0

Pouvez-vous poster un petit programme complet qui démontre le comportement que vous voyez? Cela nous aiderait à comprendre le comportement. –

Répondre

2

De C# language spec:

Le constructeur statique pour une classe exécute au plus une fois dans un domaine d'application donnée. L'exécution d'un constructeur statique est déclenchée par le premier des événements suivants à se produire dans un domaine d'application:

  • Une instance de la classe est créée.
  • Tous les membres statiques de la classe sont référencés.
+0

Oui ... Cependant dans le code ci-dessus je ne fais ni création ni référencement. En d'autres termes, le code à l'intérieur de mon bloc else ne sera jamais exécuté. – Shamika

+0

@Shamika, vous devez montrer plus de code pour nous aider. comment iniSingleton est-il initialisé? – notnoop

+0

J'ai ajouté un exemple de code. – Shamika

3

Je vous suggère de lire article Jon Skeet sur le modèle Singleton en C# et its appendix au sujet de chargement paresseux, etc. Vous aurez une meilleure compréhension des problèmes de mise en œuvre.

+1

En effet, si la classe OP n'a pas de constructeur statique alors elle sera marquée comme beforefieldinit par le compilateur et l'initialisation de type peut avoir lieu à tout moment (avant tout accès aux champs statiques, bien sûr). – LukeH

+0

J'ai implémenté ma classe singleton en tant que "Quatrième version - pas tout à fait paresseuse, mais thread-safe sans utiliser de verrous". Je suis toujours confus avec le comportement que je vois dans mon application si. – Shamika

+0

@Shamika: Si votre singleton est implémenté comme la quatrième version de l'article de Jon, vous ne devriez pas voir le comportement que vous décrivez dans la question. – LukeH

Questions connexes