为什么VB.Net中有每个表单的默认实例,而C#中没有?
我只是想知道有一个(Name)属性,它代表表单类的名称。此属性在命名空间中用于唯一标识窗体是其实例的类,对于Visual Basic,该属性用于访问窗体的默认实例 现在,这个默认实例来自何处,为什么C#不能有一个与此等效的方法 例如,要在C#中显示表单,我们可以执行以下操作:为什么VB.Net中有每个表单的默认实例,而C#中没有?,c#,vb.net,winforms,C#,Vb.net,Winforms,我只是想知道有一个(Name)属性,它代表表单类的名称。此属性在命名空间中用于唯一标识窗体是其实例的类,对于Visual Basic,该属性用于访问窗体的默认实例 现在,这个默认实例来自何处,为什么C#不能有一个与此等效的方法 例如,要在C#中显示表单,我们可以执行以下操作: // Only method Form1 frm = new Form1(); frm.Show(); public partial class Form2 : Form { [ThreadStatic] pri
// Only method
Form1 frm = new Form1();
frm.Show();
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;
}
}
}
但是在VB.Net中,我们有两种方法来实现这一点:
第一种常用方法
表格1.Show()
"第二种方法,
Dim frm作为新表格1()
frm.Show()
Form1
,是Form1
的实例还是Form1
类本身?正如我前面提到的,表单名是VB.Net中的默认实例。但是我们也知道Form1
是在Designer
中定义的一个类,那么实例和类名的名称怎么可能相同呢?
如果Form1
是一个类,则没有名为Show()的(静态\共享)方法。
那么这个方法是从哪里来的呢基本上,VB是在背后向您的项目中添加大量代码 查看正在发生的事情的最简单方法是构建一个最小的项目,并使用Reflector查看它。我刚刚用VB创建了一个新的WinForms应用程序,并添加了以下类:
Public Class OtherClass
Public Sub Foo()
Form1.Show()
End Sub
End Class
当反编译为C#时,Foo的编译代码如下所示:
MyProject.Forms
是生成的MyProject
类中的一个属性,类型为MyForms
。当您开始深入研究这个问题时,您会看到其中包含大量生成的代码
当然,C#可以做到这一切——但它通常不会在你背后做那么多。它为匿名类型、迭代器块、lambda表达式等构建额外的方法和类型,但与VB在这里的方式不同。C#构建的所有代码都与您编写的源代码相对应——只是经过了巧妙的转换
当然,这两种方法都存在争议。就我个人而言,我更喜欢C#方法,但这可能并不奇怪。我不明白为什么应该有一种方式来访问表单的实例,就像它是一个单例,但只针对表单。。。基本上,无论我使用的是GUI类还是其他任何东西,我都喜欢该语言以相同的方式工作。这是在VS2005附带的VB.NET版本中添加回该语言的。根据流行的需求,VB6程序员很难看出类型和对该类型对象的引用之间的区别。代码段中的Form1与frm。这是有历史的,VB直到VB4才得到类,而窗体一直回到VB1。这对程序员的思维来说是相当严重的,理解这种差异对于编写有效的面向对象代码非常重要。C#没有这个的很大一部分原因 您也可以在C#中获得这一点,尽管它不会很干净,因为C#不允许像VB.NET那样向全局命名空间添加属性和方法。您可以在表单代码中添加一点胶水,如下所示:
// Only method
Form1 frm = new Form1();
frm.Show();
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程序员绝望地放弃了线程。抽象存在漏洞时的问题。你最好不要这样做。“他们在生成的IL中有什么不同”:下载并使用.NET Reflector自己找出答案。它非常有用,而且是免费的。我不想在C#中使用这个“特性”。。。这只是一个隐藏需要创建类实例才能使用它的事实的技巧。这真是个糟糕的主意!另外,它的文档记录非常糟糕,并且有意外和危险的副作用(例如,每个线程都有自己的te形式的“默认实例”)@ThomasLevesque我不想要这个功能。。我只是想知道它是怎么做到的,有没有可能……)Form1.Show()正在生成错误
“WindowsApplication2.Form1”无法通过其默认实例引用自身;使用“我”来代替。
@Javed:那么你可能不是从不同的类使用它,就像我在我的示例中一样。MyProject.Forms是在运行时生成的?@Kiquenet:不是,它是在编译时生成的。它被添加到VB.Net的一个重要原因是帮助将现有代码从VB1-3移植到VB.Net,由于没有其他选择,该功能将被使用。这就是为什么我很高兴添加了它:我个人认为不应该在新代码中使用它。另外,尽管我支持此功能,并且有过一些VB6的使用经验,但我个人认为我在理解类型和对类型实例的引用之间的区别方面没有任何问题:)因此基本上VB.NET语言被修改了,因为用户太笨了,无法理解OOP。。。我总是惊讶于这种语言在这么多方面都存在缺陷,但仍然具有与C#几乎相同的特性。@ThomasLevesque:“太蠢了以至于无法理解OOP”?不,我建议你停止这种想法。Hans Passant的回答表明,在VB4之前,VB中不存在类,因此需要将此功能放在VB.NET中,以简化从VBX到VB.NET的项目升级。如果您尝试将任何非平凡的VBX应用程序升级到VB.NET,您将知道可能会出现多少错误,并且您将欣赏任何减少开发人员工作量的“非标准”语言调整。是的,MarkJ是对的,它不应该是b