2012-01-19 49 views
5

有人可以向我解释这个吗?为什么我可以调用Form.Close()如果它不是一个静态方法

在Visual Studio 2010中,创建一个VB.net Windows窗体应用程序。添加2个窗体:Form1和Form2。在Form1加载事件类型Form2.Close()中。现在,如果我们查看方法定义Close()不是静态(共享)方法。那么这怎么可能在运行时编译或工作。此外,在C#和Form2.Close()中做同样的事情。不编译。

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

+2

这就是Microsoft将“MS Access”开发人员负责“VB.NET”以使其更加吸引“VB6/'VBA'人群。随之而来的灾难...... – ja72

+0

@ ja72当然,任何被称为“VB.x”的点都至少对VB6和VBA用户有一些吸引力。也就是说,我讨厌VB6中的这个特性,而且它的延续是学习C#的另一个原因,所以我认为它只是吸引了一些VB人群。 –

回答

6

你已经发现了一个名为“default instance”的VB.NET-ism。

编译器实际上是发出这样的:

My.Forms.Form2.Close(); 

有一个很好的writeup of that feature here

默认实例是该类型的VB应用程序框架创建和管理你的对象。

...

如果使用默认实例,那么你并不需要显式调用构造函数。您只需通过My.Forms对象直接访问默认实例

+3

我喜欢这个功能背后的推理:* VB的主要目标之一一直是为尽可能多的人提供能量,同时尽可能简化编程。默认表单实例的引入是为了实现这一目标。许多新接触OOP的人在VB.NET中使用对象,但他们并没有真正理解它们。*引入隐式惰性实例化单例的一个可爱理由:许多新接触OOP的人并不真正了解OOP,所以让我们来介绍一下另一个特殊功能。 – Groo

+0

在这种情况下究竟发生了什么。我的客户几乎不知道他在做什么,对OOP知之甚少。然而,他设法完成了他想要做的事情的完全相反:当他试图减少它时,他增加了程序使用的内存。 –

5

原因是VB创建了一个窗体的自动实例,如果你只是通过名字引用它们,如果它没有被捕获,可能会导致运行时产生意想不到的后果。

我没有发现可以防止这种情况的发生。

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

1

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

+1

-1。这是一个使用VB应用程序框架向默认实例发出调用的编译器。 – vcsjones

+0

使用ILSpy或类似软件查看可执行文件的生成部分。它作为一个财产实施。 – hvd

+0

它是一个属性,这只是一个实现细节,说它是一个属性并不能解释它是如何工作的。它是一个名为MyForms的编译器生成类型的属性。此外; VB.NET不提供任何暗示您正在调用属性上的“关闭”。它看起来像一个静态的调用。 – vcsjones

相关问题