我写了一个程序,允许两个class级“打架”。 无论出于何种原因,C#总是赢。 VB.NET出了什么问题?

我写了一个程序,允许两个class级“打架”。 无论出于何种原因,C#总是赢。 VB.NET出了什么问题?

static void Main(string[] args) { Player a = new A(); Player b = new B(); if (a.Power > b.Power) Console.WriteLine("C# won"); else if (a.Power < b.Power) Console.WriteLine("VB won"); else Console.WriteLine("Tie"); } 

这里是玩家:C#中的玩家A:

 public class A : Player { private int desiredPower = 100; public override int GetPower { get { return desiredPower; } } } 

VB.NET中的播放器B:

 Public Class B Inherits Player Dim desiredPower As Integer = 100 Public Overrides ReadOnly Property GetPower() As Integer Get Return desiredPower End Get End Property End Class 

这里是一个基础类。

 public abstract class Player { public int Power { get; private set; } public abstract int GetPower { get; } protected Player() { Power = GetPower; } } 

这里的问题是VB设置其字段值之前调用基础构造函数。 所以基本的Player类存储零。

 .method public specialname rtspecialname instance void .ctor() cil managed { // Code size 15 (0xf) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [base]Player::.ctor() IL_0006: ldarg.0 IL_0007: ldc.i4.s 100 IL_0009: stfld int32 B::desiredPower IL_000e: ret } // end of method B::.ctor 

提出我的意见,以答复:

我:

尝试将每个“电源”写入控制台

恶作剧:

C#:100 VB.NET:0

我:

正如我怀疑的。 看起来像VB.Net在inheritance的构造函数之前调用Base构造函数,因此VB的desiredPowervariables仍然是0,而C#反向(记住,在构造函数结束时会发生字面初始化)。

更新:
我想find一些有关这种行为的文档 (否则你会看到任何新的.Net版本可能会改变你的行为)。 从链接:

派生类的构造函数隐式调用基类的构造函数

基类对象总是在任何派生类之前构造的。 因此,基类的构造函数在派生类的构造函数之前执行。

这些是在同一页上,似乎是相互排斥的,但我认为派生类的构造函数是首先被调用的,但是假定它自己在做任何其他工作之前调用基础构造函数。 因此,构造函数的顺序不是重要的,而是文字初始化的方式。

我也发现了这个引用 ,其中清楚地表明了这个顺序是派生实例字段,然后是基础构造函数,然后派生的构造函数。

当B上的构造者完成时,两个玩家的私人成员的理论值都是100。

然而,由于C#的内部优势,CLI通常认为从该语言编译的整数和其他原始值值更高,而来自VB.NET的值则更低,即使它们包含相同的位。

发生这种情况是因为C#首先初始化类字段,而不是调用基构造函数。 VB反而是相反的,所以当你在VB中给Power赋值的时候,私有字段还没有初始化,它的值是0。