【问题标题】:Why is there a default instance of every form in VB.Net but not in C#?为什么在 VB.Net 中每个表单都有一个默认实例,而在 C# 中却没有?
【发布时间】:2011-06-09 13:42:32
【问题描述】:

我只是想知道有 (Name) 属性,它表示 Form 类的名称。此属性在命名空间中用于唯一标识 Form 是其实例的类,并且在 Visual Basic 的情况下,用于访问表单的默认实例。

既然这个 Default Instance 是从哪里来的,为什么 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()
  1. 我的问题来自第一种方法。这是什么Form1,它是Form1 的实例还是Form1 类本身?现在正如我上面提到的,表单名称是 VB.Net 中的默认实例。但是我们也知道Form1 是在Designer 中定义的类,那么实例名称和类名称怎么可能相同呢? 如果Form1 是一个类,则不存在名为 Show() 的 (Static\Shared) 方法。 那么这个方法是从哪里来的呢?

  2. 它们在生成的IL中有什么区别?

  3. 最后,为什么 C# 不能有类似的功能?

【问题讨论】:

  • “它们在生成的 IL 中有什么不同”:下载并使用 .NET Reflector 自己找出来。它非常有用,而且免费。
  • 我不想在 C# 中使用这个“功能”...这只是一个技巧,可以隐藏您需要创建一个类的实例才能使用它的事实。这真是一个可怕的主意!另外,它的文档记录很差,并且有意想不到和危险的副作用(例如,每个线程都有自己的“默认实例”形式)
  • @ThomasLevesque 我不想要那个功能.. 我只是想知道它是如何完成的以及是否可能.. :)

标签: c# vb.net winforms


【解决方案1】:

这是在 VS2005 附带的 VB.NET 版本中添加回语言的。由于普遍的需求,VB6 程序员很难看出类型和对该类型对象的引用之间的区别。您的 sn-p 中的 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 语句中的代码移到其自己的私有方法中以使其高效,为了清楚起见,我将其保留为这种方式。

顺便说一句,sn-p 中的 [ThreadStatic] 属性使许多 VB.NET 程序员彻底绝望地放弃了线程。抽象泄漏时的问题。你真的最好不要这样做。

【讨论】:

  • 将其添加到 VB.Net 的一个重要原因是帮助将现有代码从 VB1-3 移植到 VB.Net,因为没有其他选择,该功能将被使用。这就是我很高兴它被添加的原因:我个人认为它不应该在新代码中使用。此外,尽管我支持此功能并且对 VB6 有一些经验,但我认为我个人在理解类型和对该类型实例的引用之间的区别方面没有任何问题:)
  • 所以基本上 VB.NET 语言被修改了,因为用户太愚蠢了,无法理解 OOP……我总是惊讶于这种语言如何在这么多方面存在缺陷,同时仍然有几乎与 C# 相同的功能。
  • @ThomasLevesque:'太愚蠢了,无法理解 OOP'?不,我建议你停止这种想法。 Hans Passant 的回答表明 VB 中直到 VB4 才存在类,因此需要将此功能放入 VB.NET 中以简化从 VBX 到 VB.NET 的项目升级。如果您尝试将任何重要的 VBX 应用程序升级到 VB.NET,您就会知道您可能会遇到多少错误,并且您会喜欢任何可以减少开发人员工作量的“非标准”语言调整。是的,MarkJ 是对的,它不应该在新代码中使用,但 VB 开发人员绝对不傻,否则他们不会出现。
  • @AlexEssilfie,我并不是说 VB.NET 用户 太愚蠢了,我是说这种语言的设计就像他们一样。我理解与旧代码兼容的必要性,但这应该是您明确启用的可选功能,当然不是新项目的默认设置。
  • 可怕的罪行正在以更高的理想的名义犯下。例如,Option Strict Off
【解决方案2】:

基本上,VB 是在背后为您的项目添加大量代码。

查看正在发生的事情的最简单方法是构建一个最小项目并使用 Reflector 查看它。我刚刚用 VB 创建了一个新的 WinForms 应用程序并添加了这个类:

Public Class OtherClass    
    Public Sub Foo()
        Form1.Show()
    End Sub
End Class

Foo 的编译代码在反编译为 C# 时如下所示:

public void Foo()
{
    MyProject.Forms.Form1.Show();
}

MyProject.Forms 是生成的MyProject 类中的一个属性,类型为MyForms。当您开始深入研究时,您会在其中看到大量生成的代码。

当然,

C#可以完成所有这些工作 - 但它通常没有背着你做那么多事情的历史。它为匿名类型、迭代器块、lambda 表达式等构建额外的方法和类型——但与 VB 在这里所做的方式不同。 C# 构建的所有代码都与您编写的源代码相对应 - 只是经过巧妙的转换。

当然,这两种方法都有争论。我个人更喜欢 C# 方法,但这可能不足为奇。我不明白为什么应该有一种访问表单实例的方法,就好像它是一个单例但 only 用于表单......我喜欢 language基本上,无论我使用 GUI 类还是其他任何东西,都以相同的方式工作。

【讨论】:

  • Form1.Show() 产生错误'WindowsApplication2.Form1' cannot refer to itself through its default instance; use 'Me' instead.
  • @Javed:那么大概你没有从不同的班级使用它,就像我在我的例子中一样。
  • MyProject.Forms 在运行时生成?
  • @Kiquenet:不,它是在编译时生成的。
猜你喜欢
  • 2014-03-03
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多