【问题标题】:When are default form instances created?什么时候创建默认表单实例?
【发布时间】:2014-09-14 09:52:54
【问题描述】:

在 VB.NET 中,表单实例的启动顺序和处理非常奇怪。当您引用表单时,例如 Form2.Textbox1.Text = "Foo",CLR 会自动使用在后台创建的表单实例,并且可以通过 My.Forms.Form2 直接访问。

我正在使用通过自定义Sub Main() 启动的 WinForms 应用程序。这里应用程序通过调用Application.Run(frmMain) 运行。

由于我有多个需要初始化的表单,我想确切地知道实际表单实例的创建时间。它们都是在Application.Run 创建的还是仅在我调用Form2.Show() 时创建的?我现在的启动顺序如下:

  1. 子主()
  2. Sub Main() 调用Application.Run(frmMain)
  3. frmMain.Load 致电frmNotMain.Show()

我现在可以在哪里找到像 My.Forms.frmNotMain = New frmNotMain 这样的行,所以创建实例的位置并不明显。

提前谢谢你。

【问题讨论】:

    标签: vb.net winforms forms


    【解决方案1】:

    According to MSDN:

    当您通过 My.Forms.Form1 访问 Form 时,工厂方法会检查 Form1 的实例是否已打开。如果是,则返回该实例。否则,将创建并返回 Form1 的一个实例。

    所以本质上它是在显示之前创建并调用Sub New(不是在某处创建并在需要时保留)。该链接包含此代码,显示了它如何创建这些默认实例:

    'Code ... generated by the compiler
    Public m_Form1 As Form1
    Public Property Form1() As Form1
        Get
            m_Form1 = Create__Instance__ (Of Form1)(m_Form1) 
            Return m_Form1 
        End Get
        Set(ByVal Value As Form1)
         If Value Is m_Form1
        Return
           End If
           If Not Value Is Nothing Then
              Throw New ArgumentException("Property can only be set to Nothing.")
           End If
           Dispose__Instance__ (Of Form1)(m_Form1)
        End Set
    End Property
    

    但是,您说的是默认(“怪异”)实例方法,一开始是不明智的。这主要是为了提供与 VB6 类型代码的兼容性,您只需执行 myForm.Show() 来实例化并显示表单(可能适用于不真正了解实例化或 OOP 的修补程序)。

    表单是类,应该通过显式创建实例来处理;所以,一般来说:

    Dim frm As New frmMain                ' NEW creates the instance
    frm.Show
    

    您可以在表单的Sub New 中的InitializeComponent 上设置断点,以查看它何时被调用。要创建对它的全局引用,就像您可能对任何其他类一样:

    Friend frmMain As MainForm          ' no instance yet
    Friend myMain As MainClass
    
    Public Sub Main
    
        ' do this before any forms are created
        Application.EnableVisualStyles()
    
        myMain = New MainClass()
        myMain.DoStuff()
    
        frmMain = New MainForm()         ' instanced (NEW)
    
        Application.Run(frmMain)
    End Sub
    

    同样:

    Dim frm2 = New frmNotMain       ' declare and instance
    
    ' short for:
    Dim frm2 As frmNotMain          ' declare  frm2
    frm2 = New frmNotMain           ' create instance
    
    frm2.Show 
    

    在所有情况下,当您使用New 运算符创建新表单时,将调用您的表单的Sub New。 VB 试图通过重复使用New 来明确这一点,但使用默认实例实际上隐藏在表单工厂中。

    【讨论】:

    • 谢谢 Plutonix。这解释了它。我认为通过代码并将其转换为根本不使用默认实例是值得的。您是否知道是否存在禁止使用这些实例的编译器设置?
    • 在许多用例中,默认实例可能会导致中等复杂应用出现问题。根据范围,myFrm可能引用现有实例,或者它可能创建一个全新的实例,从而导致各种混乱。
    • 非常正确。我非常喜欢 VB.NET,但如果不花时间真正深入了解它,后台发生的事情并不总是很明显。这可能会导致应用程序出现非常奇怪的行为。
    • @Jens - 在项目的 VB 设置中,您可以禁用“应用程序框架”,但我不确定这是否不允许使用自动创建的实例。
    • 我已经这样做了,以使用自定义输入方法 (Sub Main()),正如我在我的问题中所写的那样。但是,它并没有改变默认实例的任何内容。不过谢谢你的建议。
    猜你喜欢
    • 2019-06-13
    • 1970-01-01
    • 2018-03-02
    • 2022-11-25
    • 2010-11-08
    • 2011-05-31
    • 1970-01-01
    • 2012-02-22
    • 2014-02-07
    相关资源
    最近更新 更多