Порядок выполнения конструктора С#
В С#, когда вы делаете
Class(Type param1, Type param2) : base(param1)
является конструктором класса, выполняемого первым, а затем вызывается конструктор суперкласса или он сначала вызывает базовый конструктор?
Ответы
Ответ 1
Порядок:
- Элементы-члены инициализируются значениями по умолчанию для всех классов в иерархии
Затем, начиная с самого производного класса:
- Переменные инициализаторы выполняются для наиболее производного типа
- Цепочка конструктора определяет, какой конструктор базового класса будет называться
- Базовый класс инициализируется (рекурсия все это:)
- Выполняются тела конструктора в цепочке этого класса (обратите внимание, что их может быть больше одного, если они связаны с
Foo() : this(...)
и т.д.
Обратите внимание, что в Java базовый класс инициализируется до запуска инициализаторов переменных. Если вы когда-либо переносите какой-либо код, это важно знать о:)
У меня есть страница с более подробной информацией, если вам интересно.
Ответ 2
Он сначала вызовет базовый конструктор. Также имейте в виду, что если вы не поместите :base(param1)
после своего конструктора, будет вызван базовый пустой конструктор.
Ответ 3
Сначала создается конструктор базового класса.
Ответ 4
Не уверен, что это должен быть комментарий/ответ, но для тех, кто учится на примере, эта скрипка также иллюстрирует порядок: https://dotnetfiddle.net/kETPKP
using System;
// order is approximately
/*
1) most derived initializers first.
2) most base constructors first (or top-level in constructor-stack first.)
*/
public class Program
{
public static void Main()
{
var d = new D();
}
}
public class A
{
public readonly C ac = new C("A");
public A()
{
Console.WriteLine("A");
}
public A(string x) : this()
{
Console.WriteLine("A got " + x);
}
}
public class B : A
{
public readonly C bc = new C("B");
public B(): base()
{
Console.WriteLine("B");
}
public B(string x): base(x)
{
Console.WriteLine("B got " + x);
}
}
public class D : B
{
public readonly C dc = new C("D");
public D(): this("ha")
{
Console.WriteLine("D");
}
public D(string x) : base(x)
{
Console.WriteLine("D got " + x);
}
}
public class C
{
public C(string caller)
{
Console.WriteLine(caller + " C.");
}
}
Результат:
D C.
B C.
A C.
A
A got ha
B got ha
D got ha
D
Ответ 5
[Изменить: в то время, когда мне потребовалось ответить, вопрос полностью изменился).
Ответ заключается в том, что он сначала вызывает базу.
[Оригинальный ответ на старый вопрос ниже]
Вы спрашиваете, когда вы будете делать "базовый" бит вызова конструктора?
Если это так, вы будете "цепочки" вызова базы конструктора, если класс получен из другого класса, который имеет этот конструктор:
public class CollisionBase
{
public CollisionBase(Body body, GameObject entity)
{
}
}
public class TerrainCollision : CollisionBase
{
public TerrainCollision(Body body, GameObject entity)
: base(body, entity)
{
}
}
В этом примере TerrainCollision
происходит от CollisionBase
. Путем цепочки конструкторов таким образом он гарантирует, что указанный конструктор вызывается в базовом классе с поставленными параметрами, а не по умолчанию конструктором (если он есть на базе)
Ответ 6
Ваш вопрос немного неясен, но я предполагаю, что вы хотели спросить следующее
Когда я вызываю базовый конструктор для моего объекта XNA против использования конструктора невыполнения по умолчанию
Ответ на этот вопрос сильно зависит как от вашего сценария, так и от базового объекта. Не могли бы вы пояснить немного ниже:
- Что такое сценарий
- Каков тип базового объекта
TerrainCollision
?
Мой лучший ответ заключается в том, что в случае, когда у вас есть параметры, которые совпадают с параметрами конструктора базового класса, вы почти наверняка будете его называть.
Ответ 7
Механизм конструктора намного лучше, поскольку он оставляет приложение использовать цепочку конструкторов, и если вы должны расширить приложение, оно позволяет через наследование возможность минимального изменения кода.
Статья Джона Скита