C# - что на самом деле означает" деструкторы не наследуются"?

раздел 10.13, деструкторы,Спецификация Языка C# 3.0 указано следующее:

деструкторы не наследуются. Таким образом, класс не имеет деструкторов, кроме того, который может быть объявлен в этом классе.

раздел деструкторов Руководство По Программированию На C# содержит пример, демонстрирующий, как вызываются деструкторы в иерархии наследования, включая следующие заявление:

...деструкторы для ... классы вызываются автоматически и по порядку от наиболее производных к наименее производным.

Я исследовал это с различными практическими примерами, в том числе с базовым классом, который определяет деструктор, с производным классом, который наследует от базового класса и не определяет деструктор. Создание экземпляра производного класса, позволяющего всем ссылкам на экземпляр выходить за пределы области а затем принудительная сборка мусора демонстрирует, что деструктор, определенный в базовом классе, вызывается при завершении экземпляра производного класса.

мой вопрос в том, что на самом деле означает" деструкторы не наследуются", поскольку, хотя вы не можете вызвать деструктор явно, деструкторы в цепочке наследования вызываются автоматически, а деструкторы базового класса вызываются, даже если производный класс не определяет деструктор?

связано ли это с каким-то тонким семантическим различием, что завершение реализуется сборщиком мусора, а не языком/компилятором C#?

редактировать 1:

в то время как спецификация языка C# также утверждает ,что" конструкторы экземпляров не наследуются", поведение по отношению к конструкторам значительно отличается от дескструкторов и лучше соответствует IMO с" не унаследованной " терминологией, как показано в Примере ниже:

  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();

приведенный выше пример демонстрирует, что конструкторы базового класса будут вызываться при завершении экземпляра производного класса, даже если производный класс явно не определяет деструктор.

моя точка зрения просто я столкнулся со многими людьми, которые не понимают или не понимают, что это происходит, и значительная часть причины этого-утверждение "деструкторы не наследуются".

Edit 2:

спецификация языка C# также заявляет следующее и дает пример кода реализации под капотом:

деструкторы реализуются путем переопределения виртуального метода Finalize в системе.Объект. Программы на C# не разрешено переопределять этот метод или вызывать его (или переопределяет его) напрямую.

поскольку реализация под капотом фактически основана на наследовании, как указано выше, я думаю, что мой вопрос действителен, и я не думаю, что любой из ответов, которые я получил до сих пор, правильно рассмотрел вопрос - что на самом деле означает "деструкторы не наследуются"?

1 ответов


Это не вопрос победы. Я изо всех сил пытаюсь понять ваши вопросы, но вы, кажется, озабочены тем, чтобы защитить себя от полностью воображаемых атак.

оставляя это в стороне, и учитывая ваши вопросы по одному:

мой вопрос в том, что делает " деструкторы не наследуются" на самом деле означает, поскольку, хотя нельзя называть деструктор явно, деструкторы в цепочка наследования называется автоматически, и базовый класс деструкторы вызываются, даже если производный класс не определить деструктор?

Это на самом деле означает, что деструкторы базового класса не являются членами производного класса.

мой встречный вопрос: "почему вы считаете, что факты, которые (1) Вы не можете вызвать деструктор напрямую, (2) деструкторы в цепочке наследования вызываются автоматически при сборе и (3) деструкторы базового класса вызываются, даже если производный класс не определяет конструктор, имеют никакого отношения ни по вопросу о том, является ли деструктор базового класса членом производного класса?

относится ли это к какой-то тонкой семантике различие, что финализация реализован сборщик мусора вместо языка/компилятора C#?

Неа.

язык C# - это спецификация; он ничего не реализует. Компилятор C# реализует спецификацию; он, конечно, не "реализует завершение". CLR-это то, что реализует завершение.

независимо от этого, тот факт, что деструкторы в базовом классе не являются членами производного класса, не имеет никакого отношения к тому, как завершение реализуется сборщиком мусора CLR.

мы вернемся к вопросу семантики завершения CLR и почему они не имеют отношения к вопросу наследования, в конец.

в то время как спецификация языка C# также заявляет что "конструкторы экземпляров не унаследованное", поведение в отношении конструкторам значительно отличающийся от desctructors, и пригонки лучше ИМО с "не унаследованным" терминология

хорошо, я принимаю, что вы верите в это. почему вы считаете, что это поведение имеет отношение к вопросу наследования? Я ни в малейшей степени не понимаю, почему вы в это верите. Для наследования важно, является ли рассматриваемая сущность членом производного типа просто в силу того, что она является членом базового типа.

Я согласен, что тот факт, что конструктор для базового типа не может быть вызван непосредственно через конструкцию производного типа, в которой отсутствует этот конструктор, согласуется с тем фактом, что конструкторы не наследуются. Я просто не понимаю, как это относится к вопросу о том, наследуются ли деструкторы.

A более уместным фактом является то, что базовый класс с открытым конструктором без параметров имеет этот конструктор, вызываемый, когда производный класс, которому не хватает открытого конструктора без параметров, строится с его конструктором по умолчанию. Производный класс не наследование открытый конструктор без параметров базового класса, но тем не менее он вызывается. Если вы принимаете, что конструктор, не унаследованный, может быть вызван таким образом, то почему бы не принять, что деструктор также вызывается с помощью похожая семантика?

Я просто хочу сказать, что у меня есть встречал много людей, которые не осознать или понять, что это то, что случается, и значительная часть причина этого - "деструкторы не наследуются" заявление.

полностью согласен. Вероятно, не следует писать деструкторы, если у вас нет четкого понимания того, что такое правильная семантика. Меня пугает количество книг для начинающих C# которые рассматривают деструкторы как подходящую тему для новичков; написание правильного деструктора является одной из самых сложных основных задач в C#.

с Под капотом осуществление, по сути, основано на наследование, как было сказано выше, я считаю мой вопрос действительно

ваш вопрос совершенно действителен независимо. Но теперь вы объединяете детали реализации функции со спецификацией этой функции.

по аналогии, рассмотреть анонимный тип. Вполне разумно, что у них нет имен. Но метаданные, которые мы плюем, конечно, называют тип; CLR требует типы имеют имен. Это противоречие? Не реально. Концептуальная сущность, называемая спецификацией" анонимный тип", не имеет имени, и это имеет значение. Конечно, разработчик может свободно использовать платформу, которая не требует именования всех типов.

аналогично, наша реализация C# реализует деструкторы, плюясь IL в метод, который переопределяет виртуальный метод с именем Finalize. Язык C# был тщательно разработан, чтобы не зависеть от этой функции среды выполнения. Другая реализация C# совершенно свободна в выборе другого механизма для реализации деструкторов. (Возможно, нам стоит изменить спецификацию, чтобы было более ясно, что бит о том, как реализуются деструкторы, является информативной деталью реализации, а не требованием языка C#.)

но независимо от выбора деталей реализации деструкторы в базовом классе не являются членами производного класса. Так же, как, независимо от деталей реализации, анонимные типы не имеют имен.

теперь это ясно, или у вас есть еще вопросы?