Я написал программу, которая позволяет двум классам "сражаться". По какой-то причине С# всегда выигрывает. Что случилось с VB.NET?
Я написал программу, которая позволяет двум классам "сражаться". По какой-то причине С# всегда выигрывает. Что не так с 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");
}
Вот игроки:
Игрок A в С#:
public class A : Player
{
private int desiredPower = 100;
public override int GetPower
{
get { return desiredPower; }
}
}
Игрок B в VB.NET:
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;
}
}
Ответы
Ответ 1
Проблема здесь в том, что 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
Ответ 2
Поощрение моих комментариев к ответу:
Me:
Попробуйте написать каждую "мощность" на консоли, а
Prankster:
С#: 100 VB.NET: 0
Me:
Как я и подозревал. Похоже, что VB.Net вызывает конструктор Base перед наследуемым конструктором, и поэтому переменная VB wishPower по-прежнему равна 0, тогда как С# делает это в обратном порядке (помните, что буквальная инициализация происходит в конце конструктора).
Update:
Я хотел найти некоторую документацию о поведении (в противном случае вы смотрите на поведение, которое может измениться из-под вас с любым новым выпуском .Net). По ссылке:
Конструктор производного класса неявно вызывает конструктор для базового класса
и
Объекты базового класса всегда создаются перед любым производным классом. Таким образом, конструктор базового класса выполняется перед конструктором производного класса.
Те, что находятся на одной странице и кажутся взаимоисключающими, но я полагаю, что это означает, что сначала вызывается конструктор производного класса, но предполагается, что он сам вызывает базовый конструктор, прежде чем выполнять какую-либо другую работу. Поэтому он не создает порядок, важный, но способ инициализации литералов.
Я также нашел эту ссылку, в которой четко сказано, что порядок - это производные экземпляры, затем базовый конструктор, а затем производный конструктор.
Ответ 3
К моменту завершения конструктора на B оба игрока будут иметь теоретическое значение 100 в своих частных членах.
Однако из-за превосходных внутренних элементов С# CLI обычно рассматривает целые числа и другие значения примитивных значений, скомпилированные с этого языка, чтобы быть выше, а из VB.NET - ниже, даже если они содержат одни и те же биты.
Ответ 4
Это происходит потому, что С# сначала инициализирует поля класса, а не конструкторы базовых вызовов.
VB вместо этого делает обратное, поэтому, когда в VB вы назначаете свое значение Power, частное поле еще не инициализировано, а его значение равно 0.