一尘不染

为什么在VB.Net中有每个表单的默认实例,但在C#中却没有?

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()
  1. 我的问题来自第一种方法。这是什么Form1,它是类的实例 Form1还是Form1类本身?现在,如上所述,表单名称是VB.Net中的Default实例。但是我们也知道这Form1是一个定义的类,Designer因此实例名和类名的名称如何相同?如果Form1是一个类,则没有名为Show()的(静态\共享)方法。那么这种方法从何而来呢?

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

  3. 最后,为什么C#不能做到这一点呢?


阅读 222

收藏
2020-05-19

共1个答案

一尘不染

这已添加回VS2005附带的VB.NET版本的语言中。根据普遍的需求,VB6程序员很难理解类型与对该类型对象的引用之间的区别。您的摘要中的Form1 vs
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程序员完全绝望地放弃了线程。抽象泄漏时的问题。你是 真正的 富裕都没有这样做。

2020-05-19