【问题标题】:When are inline static variables initialized in a class?什么时候在类中初始化内联静态变量?
【发布时间】:2010-08-10 13:55:16
【问题描述】:

假设我们有这样一个类:

Public Class Question 

    Private Shared _field as Integer = CrazyIntegersRepository.GetOne()

    ' Some other useful things go here

End Class

GetOne 方法抛出异常...我们如何管理它?将其重写为静态构造函数是一种好习惯吗?
如果我们将 GetOne 方法留在内联 _field 声明中,什么时候会执行它?

【问题讨论】:

    标签: .net vb.net class static


    【解决方案1】:

    注意:这里我假设 VB 的工作方式与 C# 相同。如果他们对此有不同意见,我会感到惊讶。

    如果你把它留在那里(并且没有静态构造函数),它将取决于你使用的 .NET 版本。它只保证“在第一次引用静态字段之前的某个时间点”运行。您甚至可以创建实例并且类型初始化程序可能无法运行!如果你有一个静态构造函数(即使是一个空的),类型初始化器将在第一次引用任何构造函数或任何静态成员之前运行直接。 (基本上,几乎你用它做的任何事情都会初始化它。)

    与 .NET 3.5 相比,.NET 4 中实际观察到的行为变得更加懒惰,as I blogged about。请注意,这只是在谈论桌面框架;我不知道 Silverlight 或 Compact Framework 是做什么的。

    如果该方法可以抛出异常,我会很想首先在方法调用中更懒惰地这样做,也许会适当地缓存结果。这样,该方法可以让异常冒泡,调用者可以稍后再试。如果您正在考虑这是一个潜在的暂时性异常,那么这是合适的。如果它表明整个系统无法使用,则可以让类型初始化程序失败。

    【讨论】:

    • 据我所见,一旦类型初始化程序抛出异常,就无法恢复。避免这种情况的唯一方法是防止异常冒泡,要么在静态构造函数中捕获它(当字段在那里初始化时),要么在字段初始化到的辅助方法中捕获它。我在这里有什么遗漏吗?
    • @Steven:正如我所说,我的方法通常是将它从类型初始化中移除 - 仅在您需要时计算它,然后让异常冒泡到调用者。
    • 很公平。我猜这将是Lazy<T> 的理想场所。
    • @Steven:我不知道Lazy<T> 是否允许重试,但如果允许,是的:)
    • 这里没有空间扔代码,但我相信这是可能的。再次感谢。
    【解决方案2】:

    关于您关于管理可能的异常的问题,请根据您的直觉来解决这个问题。任何可以创建异常的代码都应该放入方法中。在这种情况下,构造函数将是最好的地方。所以也许是这样的:

    Public Sub New()
        Try
            _field as Integer = CrazyIntegersRepository.GetOne()
        Catch ex As Exception
            'log it / deal with it as you will
        End Try
    End Sub
    

    【讨论】:

      【解决方案3】:

      如果你按照 p.campbell 的建议去做,你必须至少声明一个类的实例才能初始化 _field 变量。我假设,根据变量声明中的 Shared 关键字,您希望它可以从类的所有实例中访问,无论它们是否已被专门初始化。

      为了实现该功能,您必须按如下方式修改您的类:

      Public Class Question 
      
          Private Shared _field as Integer
      
          Shared Sub New()
              _field = CrazyIntergersRepository.GetOne()
          End Sub
          ' Some other useful things go here
      
      End Class
      


      使用此方法,_field 变量将在第一次使用该类时被初始化,因为默认构造函数被声明为 Shared。您可以选择将该方法包装在 Try...Catch 块中,以捕获可能发生的异常。

      【讨论】:

        猜你喜欢
        • 2012-02-01
        • 1970-01-01
        • 2012-03-10
        • 2019-09-22
        • 1970-01-01
        • 2023-03-22
        • 1970-01-01
        • 2011-03-30
        相关资源
        最近更新 更多