vb.net 中的 Static 局部变量是否不适用于一次性对象?

Is Static local variable in vb.net unsuitable for disposable objects?

局部 Static 变量是否不能用于一次性对象?这种情况的主要问题是:Dispose() 可能永远不会被调用。

示例:

Sub DrawText(text As String, fontFamily As Font)
    Static cachedFont As Font = Nothing
    If cachedFont Is Nothing OrElse fontFamily <> cachedFont.Family Then
        cachedFont = New Font(fontFamily)
    EndIf
    'now draw text using cachedFont
End Sub

这种情况下,是否只有将局部静态变量转换为局部class变量(在Sub Dispose(disposing As Boolean)中处理)?

是的,如果你想处理掉它们是不行的。

Static 局部变量编译为

  • Shared 过程中:
    • Shared class 级别的字段变量
  • 在非Shared实例方法中:
    • 到 class 级别的实例字段变量

...哪个名称派生自方法名称和变量名称以确保它在每种类型中都是唯一的。

Shared 变量在应用程序的生命周期内永远不会被释放,因为您只能释放实例。当您调用 instance.Dispose 或使用 Using 语句时,实例变量会被释放。

但是 CLR 中的垃圾收集器不会(也不能)处理非托管对象。所以问题是你不能从 Dispose 中处理这些对象,因为它超出了局部变量的范围。因此,如果您需要清理 Dispose 中的非托管资源,则无法使用 Static 局部变量来执行此操作,因为您无法访问它们。

值得一读:

遗憾地说,在使用 VS2015 的 Memory Usage Tool 检查后,我可以确认静态实例 NOT GC'ed when closing/disposing 例如一个表单使用它们。

要测试它,请创建一个包含两个表单的项目。在 Form2 的 Form2_Load 事件中声明并向静态 List(Of Font) 添加一些字体。在 Form1_Load 中创建并显示 Form2 的实例。
使用 Debug->Performance and Diagnostics 菜单选项执行项目,使用 Memory Usage 行为。
您会弹出两个表单。
关闭 Form2。单击 Memory Usage Tool window 中的 Force GC 按钮并拍摄内存快照。
关闭 Form1 以停止执行。

单击快照 1 中的 nnnn objects link,将打开一个新的 window。取消选中 window.
右上角下拉按钮中的 Collapse small objects 在搜索框中输入 'font',您将看到内存中剩余的所有字体。