2009-12-17 5 views
0

Недавно я заметил следующий интересный сценарий в одном из приложений, которые я разрабатываю с помощью .NET 3.5. В этом конкретном приложении у меня есть объект singleletion, к которому я обращаюсь как статическая переменная. Я выяснил, что время выполнения .NET должно инициализировать этот объект singleton в первый раз, когда я его получаю, но, похоже, это не так. .NET runtime инициализирует его, прежде чем я получу доступ к этому частному объекту. Ниже некоторый peudo код,Как компилятор JIT решает, когда инициализировать статические конструкторы

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

Даже во время выполнения моего код выполняется только код в стороне, если заявление среды .NET еще инициализирует одноплодную объект. В некоторых запусках приложений мне вообще не нужно обращаться к этому объекту pariticualr!

Также я не вижу такого поведения с отладочными сборками. Кажется, что это связано с оптимизированными сборками (выпуски).

Является ли это ожидаемым поведением среды выполнения .NET?

Update:

Ниже фактический код,

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")); 
     } 

Даже если мое приложение не выполняет код в сторону еще, если блокировать класс MOSSStateHandler инициализируются.

+0

Можете ли вы объяснить нам причину, по которой вам нужно выполнить проверку и где вы выполняете этот код? Очень странно это делать, это пахнет плохим дизайном. – jmservera

+0

Ну, я больше заинтересован в получении объяснения того, как .NET runtime инициализирует статические классы. Над кодом внутри метода и в зависимости от значения флага initSingletion мне нужно поддерживать некоторое состояние в моем приложении, используя этот статический класс. – Shamika

+0

Можете ли вы опубликовать небольшую полную программу, демонстрирующую поведение, которое вы видите? Это поможет нам понять поведение. –

ответ

2

От C# language spec:

статический конструктор для класса выполняется не более одного раза в данной предметной области. Выполнение статического конструктора инициируется первым из следующих событий в домене приложения:

  • Создан экземпляр класса.
  • Ссылка на любой из статических членов класса.
+0

Да ... однако в приведенном выше коде я не создаю и не ссылаюсь. Другими словами, код внутри блока else никогда не будет выполнен. – Shamika

+0

@Shamika, вам нужно показать больше кода для нас, чтобы помочь. как инициализируется iniSingleton? – notnoop

+0

Я добавил несколько примеров кода. – Shamika

3

Я предлагаю вам прочитать Джон Скит article о Singleton шаблон в C#, и its appendix о ленивой загрузке и т.д. Вы получите лучшее представление о вопросах реализации.

+1

Действительно, если класс OP не имеет статического конструктора, он будет отмечен как 'beforefieldinit' компилятором, и инициализация типа может возникнуть в любое время (до любого доступа к статическим полям, конечно). – LukeH

+0

Я реализовал мой одноэлементный класс как «Четвертая версия - не такая ленивая, но потокобезопасная без использования блокировок». Я все еще путаюсь с поведением, которое я вижу в своем приложении. – Shamika

+0

@Shamika: Если ваш синглтон реализован как четвертая версия статьи Джона, вам не следует видеть поведение, которое вы описываете в вопросе. – LukeH

Смежные вопросы