C# JIT编译器如何决定何时初始化静态构造函数

C# JIT编译器如何决定何时初始化静态构造函数,c#,.net,static,jit,C#,.net,Static,Jit,最近,我在使用.NET3.5开发的一个应用程序中观察到了以下有趣的场景。在这个特殊的UALR应用程序中,我有一个作为静态变量访问的Singleion对象。我举例说明了.NET运行时应该在我第一次访问它时初始化这个单例对象,但似乎不是这样。NET运行时在访问此particualr对象之前对其进行初始化。下面是一些培多代码 if(!initSingleton) //Do some work without using the singletion class. else //Do som

最近,我在使用.NET3.5开发的一个应用程序中观察到了以下有趣的场景。在这个特殊的UALR应用程序中,我有一个作为静态变量访问的Singleion对象。我举例说明了.NET运行时应该在我第一次访问它时初始化这个单例对象,但似乎不是这样。NET运行时在访问此particualr对象之前对其进行初始化。下面是一些培多代码

if(!initSingleton)
   //Do some work without using the singletion class.
else
   //Do some work using the singletion class.
即使在运行时,我的代码也只执行if语句中的代码。NET运行时仍然初始化singleton对象。在一些应用程序运行中,我根本不需要访问这个pariticualr对象

此外,我在调试版本中没有看到这种行为。这似乎与优化构建(发布构建)有关

这是.NET运行时的预期行为吗

更新:

下面是实际代码

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"));
        }
即使我的应用程序不执行IDE else中的代码,如果阻止初始化MOSSStateHandler类。

来自:

类的静态构造函数在给定的应用程序域中最多执行一次。静态构造函数的执行由应用程序域中发生的以下第一个事件触发:

  • 将创建该类的一个实例
  • 将引用该类的任何静态成员
发件人:

类的静态构造函数在给定的应用程序域中最多执行一次。静态构造函数的执行由应用程序域中发生的以下第一个事件触发:

  • 将创建该类的一个实例
  • 将引用该类的任何静态成员


我建议您阅读Jon Skeet关于C#中的单例模式以及关于延迟加载等的文章。您将更好地了解实现问题。

我建议您阅读Jon Skeet关于C#中的单例模式以及关于延迟加载等的文章。您将更好地了解实现问题。

是的。。。但是在上面的代码中,我既不创建也不引用。换句话说,我的else块中的代码永远不会被执行。@Shamika,您需要显示更多代码,以便我们提供帮助。iniSingleton是如何初始化的?是的。。。但是在上面的代码中,我既不创建也不引用。换句话说,我的else块中的代码永远不会被执行。@Shamika,您需要显示更多代码,以便我们提供帮助。iniSingleton是如何初始化的?您能解释一下需要执行检查的原因以及在哪里执行此代码吗?必须这样做很奇怪,它的设计很糟糕。我更感兴趣的是得到一个关于.NET运行时如何初始化静态类的解释。上面的代码在一个方法中,根据initSingletion标志的值,我需要使用这个静态类在我的应用程序中维护一些状态。你能发布一个小的、完整的程序来演示你看到的行为吗?这将有助于我们理解这种行为。我添加了一些示例代码。您可以向我们解释需要执行检查的原因以及在哪里执行此代码吗?必须这样做很奇怪,它的设计很糟糕。我更感兴趣的是得到一个关于.NET运行时如何初始化静态类的解释。上面的代码在一个方法中,根据initSingletion标志的值,我需要使用这个静态类在我的应用程序中维护一些状态。你能发布一个小的、完整的程序来演示你看到的行为吗?这将有助于我们理解行为。我添加了一些示例代码确实,如果OP的类没有静态构造函数,那么编译器会将其标记为
beforefieldinit
,并且类型初始化可以在任何时候发生(当然是在访问任何静态字段之前)。我已经将我的单例类实现为“第四个版本-不太懒惰,但线程安全,不使用锁“。我仍然对我在应用程序中看到的行为感到困惑。@Shamika:如果你的singleton是作为Jon文章的第四个版本实现的,那么你不应该看到你在问题中描述的行为。是的,我也对这个特定的行为感到困惑。”。特别是为什么我在调试构建中看不到这一点。我怀疑这与c#编译器生成的优化代码有关。事实上,如果OP的类没有静态构造函数,那么编译器会将其标记为
beforefieldinit
,并且类型初始化可以随时发生(当然,在访问静态字段之前).我已将我的singleton类实现为“第四个版本-不太懒惰,但线程安全,不使用锁”。我仍然对我在我的应用程序中看到的行为感到困惑。@Shamika:如果你的singleton是作为Jon文章的第四个版本实现的,那么你不应该看到你在问题中描述的行为。是的,我也对这个特定的行为感到困惑。特别是为什么我在调试构建中看不到这一点。我怀疑这与c#编译器生成的优化代码有关。