В C# компилятор помещает инициализацию самоинициализируемых полей перед вызов базового конструктора в конструкторе производного класса.
Так дано:
class A {
}
class B : A {
int _foo = 5;
}
мы получаем следующий IL для ctor B:
// _foo = 5;
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: stfld int32 B::_foo
// base..ctor();
IL_0007: ldarg.0
IL_0008: call instance void A::.ctor()
// }
IL_000d: nop
IL_000e: ret
Я думаю, одна из причин заключается в том, что это позволяет нам это делать:
class A {
public A() {
Bar();
}
protected virtual void Bar() {
Console.WriteLine("Base method");
}
}
class B : A {
int _foo = 5;
public B() {
}
protected override void Bar() {
Console.WriteLine(_foo); // writes 5
}
}
Тогда
A b = new B(); // will write 5, not 0.
Но если бы мы хотели использовать аргумент конструктора производного класса для установки поля вместо самоинициализации поля, нам бы не повезло:
public B(int foo) {
_foo = foo;
}
Теперь по-прежнему печатается 5, а не 42
A b = new B(42); // 5
Используете ли вы какие-нибудь приемы/хитрости, чтобы можно было устанавливать поля производного класса, от которых зависят виртуальные методы, которые можно вызывать из конструктора базового класса?
РЕДАКТИРОВАТЬ: я не совсем верю, что это строго дубликат, но вижу аргументы в пользу этого.
В любом случае , вот ОТВЕТ на этот вопрос, который не подойдет для аналогичного вопроса семилетней давности, в котором используется относительно новая возможность языка — первичные конструкторы, которые были расширен для поддержки классов и структур в C# 12
class C(int foo) : A {
protected override void Bar() {
Console.WriteLine(foo);
}
}
сейчас
A c = new C(42); // prints out 42
Подробнее здесь: https://stackoverflow.com/questions/787 ... y-are-used
Мобильная версия