提问人:Shekhar_Pro 提问时间:1/15/2011 最后编辑:Visual VincentShekhar_Pro 更新时间:6/6/2016 访问量:9008
为什么在 VB.Net 中每个窗体都有一个默认实例,而在 C# 中没有?
Why is there a default instance of every form in VB.Net but not in C#?
问:
我只是好奇地想知道有 (Name) 属性,它表示 Form 类的名称。此属性在命名空间中用于唯一标识 Form 是其实例的类,对于 Visual Basic,则用于访问窗体的默认实例。
现在这个默认实例从何而来,为什么 C# 不能有与此等效的方法。
此外,例如,为了在 C# 中显示表单,我们执行如下操作:
// Only method
Form1 frm = new Form1();
frm.Show();
但是在 VB.Net 中,我们有两种方法可以做到这一点:
' First common method
Form1.Show()
' Second method
Dim frm As New Form1()
frm.Show()
我的问题来自第一种方法。这是什么,它是类的实例还是类本身?现在,正如我上面提到的,表单名称是 VB.Net 中的 Default 实例。但是我们也知道这是一个类,那么实例和类名的名称怎么可能相同呢? 如果是一个类,则没有名为 Show() 的 (Static\Shared) 方法。 那么这种方法从何而来呢?
Form1
Form1
Form1
Form1
Designer
Form1
它们在生成的 IL 中有什么区别?
最后,为什么 C# 不能有这样的等价物呢?
答:
基本上,VB 是在背后将大量代码添加到您的项目中。
查看正在发生的事情的最简单方法是构建一个最小的项目,然后使用 Reflector 查看它。我刚刚用VB创建了一个新的WinForms应用程序,并添加了这个类:
Public Class OtherClass
Public Sub Foo()
Form1.Show()
End Sub
End Class
当反编译为 C# 时,Foo 的编译代码如下所示:
public void Foo()
{
MyProject.Forms.Form1.Show();
}
MyProject.Forms
是生成的类中的属性,类型为 。当你开始深入研究时,你会看到相当多的生成代码。MyProject
MyForms
当然,C# 可以完成所有这些工作,但它通常没有在背后做很多事情的历史。它为匿名类型、迭代器块、lambda 表达式等构建了额外的方法和类型——但与 VB 在这里所做的方式并不完全相同。C# 生成的所有代码都与您编写的源代码相对应 - 只是巧妙地转换了。
当然,这两种方法都有争论。就我个人而言,我更喜欢 C# 方法,但这可能并不奇怪。我不明白为什么应该有一种方法可以访问表单的实例,就好像它是单例一样,但仅适用于表单......基本上,无论我使用的是 GUI 类还是其他任何东西,我都喜欢这种语言以相同的方式工作。
评论
'WindowsApplication2.Form1' cannot refer to itself through its default instance; use 'Me' instead.
这在 VS2005 附带的 VB.NET 版本中被添加回语言中。根据大众的需求,VB6 程序员很难看出类型和对该类型对象的引用之间的区别。代码段中的 Form1 与 frm。这是有历史的,VB 直到 VB4 才有类,而表单一直可以追溯到 VB1。否则,这对程序员来说是相当严重的,理解这种差异对于编写有效的面向对象代码非常重要。C# 没有这个很大一部分原因。
您也可以在 C# 中恢复它,尽管它不会那么干净,因为 C# 不允许像 VB.NET 那样向全局命名空间添加属性和方法。你可以在表单代码中添加一些胶水,如下所示:
public partial class Form2 : Form {
[ThreadStatic] private static Form2 instance;
public Form2() {
InitializeComponent();
instance = this;
}
public static Form2 Instance {
get {
if (instance == null) {
instance = new Form2();
instance.FormClosed += delegate { instance = null; };
}
return instance;
}
}
}
现在可以在代码中使用 Form2.Instance,就像在 VB.NET 中使用 Form2 一样。属性 getter 的 if 语句中的代码应该移动到它自己的私有方法中,以使其高效,为了清楚起见,我保留了这种方式。
顺便说一句,该代码段中的 [ThreadStatic] 属性使许多 VB.NET 程序员在彻底绝望中放弃了线程。当抽象是泄漏时的问题。你真的最好不要这样做。
评论
Option Strict Off
评论