我写了一个程序,允许两个类“打架”。无论出于何种原因,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 在继承的构造函数之前调用 Base 构造函数,因此 VB 的desiredPower 变量仍然为 0,而 C# 则相反(记住,文字初始化发生在构造函数的末尾)。
更新:
我想找到一些关于该行为的文档(否则您所看到的行为可能会随着任何新的 .Net 版本而改变)。 来自链接:
派生类的构造函数隐式调用基类的构造函数
和
基类对象始终在任何派生类之前构造。因此,基类的构造函数在派生类的构造函数之前执行。
它们位于同一页面上,并且似乎是互斥的,但我认为这意味着首先调用派生类构造函数,但假定它本身在执行任何其他工作之前调用基构造函数。 因此,构造函数的顺序并不重要,重要的是初始化文字的方式。
我还发现了this引用,它清楚地表明顺序是派生实例字段,然后是基本构造函数,然后是派生构造函数。
发生这种情况是因为 C# 首先初始化类字段,然后调用基构造函数。 相反,VB 执行相反的操作,因此当在 VB 中将值分配给 Power 时,私有字段尚未初始化,其值为 0。
当 B 上的构造函数完成时,两个玩家的私人成员的理论值都将为 100。
但是,由于 C# 的优越内部结构,CLI 通常认为从该语言编译的整数和其他原始值较高,而来自 VB.NET 的值较低,即使它们包含相同的位。