【问题标题】:Why can I call Form.Close() if it's not a static method如果不是静态方法,为什么我可以调用 Form.Close()
【发布时间】:2012-01-19 17:16:35
【问题描述】:

谁能给我解释一下?

在 Visual Studio 2010 中,创建一个 VB.net Windows 窗体应用程序。添加 2 个表单:Form1 和 Form2。在 Form1 Load 事件中键入 Form2.Close()。现在,如果我们查看方法定义 Close() 不是静态(共享)方法。那么这怎么可能编译或在运行时工作。

此外,在 C# 和 Form2.Close() 中做同样的事情;无法编译。

发生了什么事?为什么这在 VB.net 中是可能的?执行那行代码时实际发生了什么?

【问题讨论】:

  • 当微软让MS Access 开发人员负责VB.NET 以使其对VB6/VBA 人群更具吸引力时,就会发生这种情况。灾难接踵而至……
  • @ja72 当然,所谓“VB.x”的意义在于至少对 VB6 和 VBA 用户有一定的吸引力。也就是说,我讨厌 VB6 中的这个特性,它的延续是学习 C# 的另一个原因,所以我想它只吸引了一些 VB 人群。

标签: c# vb.net winforms


【解决方案1】:

您发现了一个名为“默认实例”的 VB.NET 主义。

编译器实际上发出了这个:

My.Forms.Form2.Close();

有个不错的writeup of that feature here:

默认实例是 VB 应用程序框架为您创建和管理的那种类型的对象。

...

如果使用默认实例,则无需显式调用构造函数。您只需通过 My.Forms 对象直接访问默认实例

【讨论】:

  • 我喜欢这个功能背后的原因:VB 的主要目标之一一直是提供强大的功能,同时让尽可能多的人尽可能轻松地进行编程。引入默认表单实例是为了实现这一目标。许多刚接触 OOP 的人在 VB.NET 中使用对象,但他们并没有真正理解它们。 引入隐式惰性实例化单例的理由多么美妙:许多 OOP 新手,并不真正了解 OOP,所以让我们介绍另一个特殊功能。
  • 正是在这种情况下发生的事情。我的客户几乎不了解他在做什么,并且对 OOP 知之甚少。然而,他成功地做了与他试图做的完全相反的事情:当他试图减少程序使用的内存时,他增加了程序使用的内存。
【解决方案2】:

原因是,如果您只是按名称引用它们,VB 会自动创建一个表单实例,如果没有被捕获,可能会在运行时导致意想不到的后果。

我发现没有任何设置可以防止这种情况发生。

但是,您可以在编译时通过将默认构造函数的范围从 Public 更改为 Friend 或删除默认构造函数并添加一个需要参数的构造函数来“打破”这种行为。这些更改中的任何一个都将禁用自动表单引用。

【讨论】:

    【解决方案3】:

    你是对的,当Form2 只是一个类类型时,你不能调用Form2.Close();。然而,VB.NET 在后台创建了一个同名的属性,因此您实际上是在 Form2 的实例上调用 Close。如果您手动创建这样的属性,您可以在 C# 中执行相同的操作。它看起来像一个静态方法调用,但实际上不是。

    【讨论】:

    • -1。这是一个使用 VB 应用程序框架发出对默认实例的调用的编译器。
    • 使用 ILSpy 或类似工具查看可执行文件的生成部分。它被实现为一个属性。
    • 它是一个属性,这只是一个实现细节,说它是一个属性并不能解释它是如何工作的。它是一个名为 MyForms 的编译器生成的类型的属性。此外; VB.NET 没有提示您在属性上调用Close。它看起来像一个静态调用。
    • 是的,除了实现它的编译器生成类型的名称(我没有提到),这不是我说的吗?
    猜你喜欢
    • 2013-08-20
    • 2015-11-13
    • 2012-10-04
    • 2016-11-16
    • 2011-03-02
    • 2011-12-11
    • 2020-12-31
    • 1970-01-01
    • 2019-10-06
    相关资源
    最近更新 更多