代码之家  ›  专栏  ›  技术社区  ›  Prankster

我写了一个允许两个班“打架”的程序。无论出于什么原因,C总是赢。vb.net有什么问题?

  •  62
  • Prankster  · 技术社区  · 17 年前

    我写了一个允许两个班“打架”的程序。无论出于什么原因,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;
        }
    }
    
    4 回复  |  直到 9 年前
        1
  •  45
  •   Jb Evain    17 年前

    这里的问题是,VB在设置其字段值之前正在调用基构造函数。所以基本播放器类存储零。

    .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
    
        2
  •  16
  •   Joel Coehoorn    9 年前

    将我的评论提升为答案:

    我:

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

    恶作剧者:

    C:100 vb.net:0

    我:

    正如我所怀疑的。看起来vb.net在继承的构造函数之前调用了基构造函数,因此vb的desiredpower变量仍然是0,而c则相反(记住,文本初始化发生在构造函数的末尾)。

    更新:
    我想找一些 documentation 在行为上(否则,您将看到的行为可能会随着任何新的.NET版本而从您的下方改变)。从链接:

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

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

    它们在同一个页面上,似乎是互斥的,但我认为这意味着首先调用派生类构造函数,但假定它自己在执行任何其他工作之前调用基构造函数。因此,它不是构造函数顺序那么重要,而是文本初始化的方式。

    我也发现了 this reference ,它清楚地说明顺序是派生实例字段,然后是基构造函数,然后是派生构造函数。

        3
  •  2
  •   James Orr    17 年前

    到B上的构造函数完成时,两个参与者的私有成员的理论值都将为100。

    然而,由于C的高级内部结构,cli通常认为从该语言编译的整数和其他基元值更高,而从vb.net编译的值更低,即使它们包含相同的位。

        4
  •  1
  •   Andrea Parodi    16 年前

    这是因为C首先初始化类字段,然后调用基构造函数。 相反,vb则相反,因此当在vb中将值赋给power时,私有字段尚未初始化,其值为0。