为什么C#在基构造函数之前设置私有变量,而VB.NET则相反?

为什么C#在基构造函数之前设置私有变量,而VB.NET则相反?,c#,.net,vb.net,C#,.net,Vb.net,在比较C#代码和VB.NET时出现了一个问题,看起来完全相同的代码之间的结果完全不同。 () 给出的解释是,C#将初始化类字段,然后调用基构造函数,但VB.NET的作用正好相反 我的问题是——为什么 语言的不同有技术上的原因吗?乍一看,这两种方法似乎都同样有效,但我无法理解为什么他们不会选择相同的方法 编辑:正如“Jeffrey L Whitledge”所指出的,VB6没有继承性,因此我不认为我们可以说“保持VB.NET和VB6更密切的关系”。基本构造函数有可能在派生类构造函数运行之前向外界公开

在比较C#代码和VB.NET时出现了一个问题,看起来完全相同的代码之间的结果完全不同。 ()

给出的解释是,C#将初始化类字段,然后调用基构造函数,但VB.NET的作用正好相反

我的问题是——为什么

语言的不同有技术上的原因吗?乍一看,这两种方法似乎都同样有效,但我无法理解为什么他们不会选择相同的方法


编辑:正如“Jeffrey L Whitledge”所指出的,VB6没有继承性,因此我不认为我们可以说“保持VB.NET和VB6更密切的关系”。

基本构造函数有可能在派生类构造函数运行之前向外界公开对象。虽然人们应该经常避免这样做,但有时这是必要的。例如,一个对象可能有两个相互引用的对象,每个对象可能都有一个类不变量,即对另一个对象的引用必须是有效的。创建这样一对对象需要一个对象的构造函数将部分构造的对象传递给另一个对象,或者在满足其类不变量之前让对象的构造函数返回

如果派生类字段初始值设定项在基类构造函数运行之后才运行,并且如果基类构造函数将对象公开给外部世界,则这意味着该对象将在任何派生类初始化发生之前公开给外部世界。C#的创建者不喜欢这个想法,所以他们让派生类初始值设定项在基类构造函数之前运行

另一方面,在基类构造函数之前运行派生类初始值设定项有一个缺点:这些初始值设定项不能引用正在构造的对象。他们也无法使用传递给构造函数的任何参数。在控制权移交给基类构造函数之前,让对象部分初始化可能很好,但对于如何初始化它,存在一些严格的限制;在运行基本构造函数之前,对象可能处于完全有用的状态,也可能不处于完全有用的状态

vb.net的创建者显然认为,由于在基本构造函数之前运行初始值设定项并不能消除处理暴露于外部世界的部分构造对象的需要,而且由于它排除了使用一些有用的技术,因此最好在基本构造函数之后运行初始值设定项。这使得基级构造函数可以将其参数之一公开为字段,然后让派生类在派生类字段初始值设定项中使用该字段的值


可以说,C#方法允许人们做vb.net方法不允许做的事情,但反过来就不行了(人们可以通过简单地在构造函数的开头写入字段来实现vb风格的字段初始值设定项)。另一方面,将一个字段的声明和初始化放在一起比在一个地方声明,在另一个地方初始化更干净。糟糕的是,这两种语言都不允许指定某些特定的字段声明应遵循与规范相反的范例。

更可能的是,设计者更喜欢c#方式,但出于历史/vb6兼容性的原因,让VB.Net采用另一种方式。@Joel Coehoorn-vb6没有继承性,因此,这不能是出于历史兼容性的原因。@Joel Coehoorn:实际上,我更喜欢vb.net方式,因为vb.net字段在基本构造函数运行之前可以预料地初始化(为零),我发现这样的初始化足以满足我的需要。正如我所说,我真的不喜欢将字段的初始化和声明分开。事实上,如果一个类可以在它的构造函数中允许字段声明,并且可以将这些字段声明封装在try-catch-finally块中,那么最好的IMHO就是。VB.NET允许字段初始值设定项使用实例成员,而C#不允许。这使得在运行初始值设定项之前完全构造类对象变得非常重要。