В разделе 10.13 "Деструкторы" С# Language Specification 3.0 указано следующее:
Деструкторы не наследуются. Таким образом, класс не имеет деструкторов, отличных от того, который может быть объявлен в этом классе.
Раздел Деструкторы Руководство по программированию на С# содержит пример, демонстрирующий, как вызываются деструкторы в иерархии наследования, включая следующую инструкцию:
... деструкторы для... классов вызываются автоматически и, по порядку, из самого полученного к наименее производному.
Я исследовал это с помощью различных практических примеров, в том числе с базовым классом, который определяет деструктор, с производным классом, который наследуется от базового класса и не определяет деструктор. Создание экземпляра производного класса, позволяющего исключить все ссылки на экземпляр из области видимости, а затем принудительное удаление мусора, показывает, что деструктор, определенный в базовом классе, вызывается, когда экземпляр производного класса завершен.
Мой вопрос заключается в том, что "деструкторы не наследуются" на самом деле означает, поскольку, хотя вы не можете явно вызвать деструктор, деструкторы в цепочке наследования вызываются автоматически, а деструкторы базового класса вызывают, даже если производные класс не определяет деструктор?
Связано ли это с каким-то тонким смысловым различием, что финализация выполняется сборщиком мусора, а не языком С#/компилятором?
Изменить 1:
В то время как спецификация языка С# также заявляет, что "конструкторы экземпляров не наследуются", поведение по отношению к конструкторам существенно отличается от дескрипторов и подходит лучше ИМО с "ненасыщенной" терминологией, как показано в примере ниже:
public class ConstructorTestBase
{
public ConstructorTestBase(string exampleParam)
{
}
}
public class ConstructorTest: ConstructorTestBase
{
public ConstructorTest(int testParam)
: base(string.Empty)
{
}
}
...
// The following is valid since there is a derived class constructor defined that
// accepts an integer parmameter.
ConstructorTest test1 = new ConstructorTest(5);
// The following is not valid since the base class constructor is not inherited
// by the derived class and the derived class does not define a constructor that
// takes a string parameter.
ConstructorTest test2 = new ConstructorTest("Test");
Поведение по отношению к деструкторам сильно отличается от поведения, как показано в следующем примере, который расширяет пример предыдущего конструктора, добавляя дескриптор только к базовому классу.
public class ConstructorTestBase
{
public ConstructorTestBase(string exampleParam)
{
}
~ConstructorTestBase()
{
Console.WriteLine("~ConstructorTestBase()");
}
}
...
ConstructorTest test1 = new ConstructorTest(5);
test1 = null;
GC.Collect();
В приведенном выше примере демонстрируется, что конструкторы базового класса будут вызываться, когда экземпляр производного класса будет завершен, даже если производный класс явно не определяет деструктор.
Моя точка зрения заключается в том, что я столкнулся со многими людьми, которые не понимают и не понимают, что это происходит, и значительная часть причины этого - это выражение "деструкторы не наследуются" .
Изменить 2:
Спецификация языка С# также указывает следующее и дает пример кода реализации под капотом:
Деструкторы реализуются путем переопределения виртуального метода Finalize в System.Object. С# программам не разрешается переопределять этот метод или называть его (или его переопределения).
Поскольку реализация under-the-hood на самом деле основана на наследовании, как указано выше, я думаю, что мой вопрос верен, и я не думаю, что какие-либо из ответов, которые я получил до сих пор, рассмотрели вопрос правильно - что означает "деструкторы не наследуются" ?