假设我在函数中有一个静态变量:
Private Sub SomeFunction()
Static staticVar As String = _myField.Value
End Sub
Run Code Online (Sandbox Code Playgroud)
确切地说,_myField分配给staticVar的值是什么时候?第一次打电话给这个功能?封闭类的实例化?
Han*_*ant 10
CLR不支持此构造,因此VB.NET编译器模拟它.
创造第一.该变量被提升到类的私有字段,其名称不可写,可确保不会发生名称冲突.如果变量位于类的实例方法内,它将是一个实例字段.因此,当使用new运算符创建类的对象时,将创建.如果方法是共享的或者是模块的一部分,它将是共享字段.因此将由抖动在加载器堆中创建.
接下来的分配,更多涉及的操作.语言规则是当代码执行第一次落在Dim语句上时发生赋值.术语第一次是装一个.程序中的编译器生成了大量代码,以确保这一点.需要解决的问题是线程,递归和异常.
编译器在与隐藏变量字段相同的范围内创建另一个StaticLocalInitFlag类型的隐藏辅助字段,以跟踪变量的初始化状态.注入代码的第一部分是调用Monitor.Enter()来处理线程.与SyncLock相同.StaticLocalInitFlag用作锁定对象,注意它是一个类而不仅仅是一个布尔值.
接下来,Try和Finally语句防范异常.在Try语句中,StaticLocalInitFlag.State的值被检查为0.这可以防止在同一个线程上进行递归.然后将State设置为2以指示初始化代码正在运行.随后是作业.接下来,再次检查State以查看它是否仍为2.如果不是,那么出现严重错误并抛出IncompleteInitialization异常.
然后,Finally块将State设置为1以指示变量已初始化.接下来是对Monitor.Leave()的调用.
大量代码,96个字节的IL只是一个简单的变量.仅在不担心成本时才使用静态.
显然,变量Static
在赋值时就被实例化了。
当该行运行时,不是之前,也不是之后。
打个断点你就会看到。
Static
只是意味着该值将在调用之间持续存在。
Shared
类/模块成员在第一次访问类时、在任何Shared
构造函数之前和调用之前进行实例化,无论是类构造函数还是某些Shared
方法/属性。我想这可能就是你困惑的根源。Static
局部变量(如static
C# 中的 local )不是以这种方式实例化的。
来自 Tim Schmelter 的有趣信息是,该值似乎是使用隐藏的Shared
类级别变量在内部维护的,该变量像其他Shared
类级别变量一样实例化,但始终使用默认值。
除了访问类时出现一些实例化延迟之外,开发人员观察到的效果没有改变。这种延迟在实践中应该是检测不到的。