Вход/Регистрация
C# для профессионалов. Том II
вернуться

Ватсон Карли

Шрифт:

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

1. Класс должен выводиться из интерфейса

IDisposable
и реализовывать метод
Dispose
. Этот метод предназначен для явного вызова с помощью кода клиента для указания, что он закончил работать с объектом и требуется очистить ресурсы. (Интерфейсы будет рассмотрены позже в этом приложении.)

2. Класс должен отдельно реализовать деструктор, который рассматривается как запасной механизм, на случай, если клиент не вызывает

Dispose
.

Обычная реализация

Dispose
выглядит следующим образом:

public void Dispose {

 // очистка ресурсов

 System.GC.SuppressFinalize(this);

}

System.GC
является базовым классом, представляющим сборщика мусора.
SuppressFinalize
является методом, который информирует сборщика мусора, что нет необходимости вызывать деструктор для разрушаемого объекта. Вызов
SuppressFinalize
важен, так как имеется снижение производительности, если в объекте есть деструктор, который нужно вызывать в то время, когда сборщик мусора выполняет свою работу. Следствием этого является то, что реальное освобождение управляемой памяти, занимаемой этим объектом, будет существенно задерживаться.

Синтаксис деструктора по сути такой же в C#, как и в C++. Отметим, что в C# не требуется объявлять деструктор виртуальным, компилятор будет это подразумевать. Не требуется также предоставлять модификатор доступа:

Class MyClass {

 ~MyClass {

// очистка ресурсов

 }

}

Хотя метод

Dispose
обычно явно вызывается клиентами, C# допускает альтернативный синтаксис, который гарантирует, что компилятор примет меры, чтобы он был вызван. Если переменная объявлена внутри блока
using
, то ее область действия совпадает с блоком
using
и ее метод
Dispose
будет вызываться при выходе из блока:

using (MyClass MyObject = new MyClass) {

 // код

} // MyObject.Dispose будет неявно вызван при выходе из этого блока

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

MyClass
выводится из интерфейса
IDisposable
и реализует метод
Dispose
. Если нежелательно использовать синтаксис
using
, то можно опустить один или оба из двух шагов в последовательности деструктора (реализация
Dispose
и реализация деструктора), но обычно реализуются оба шага. Можно также реализовать
Dispose
, без привлечения интерфейса
IDisposable
, но если это делается, то снова невозможно использовать синтаксис
using
, чтобы для экземпляров этого класса
Dispose
вызывался автоматически.

Наследование

Наследование работает в основном таким же образом в C#, как и в C++, с тем исключением, что множественная реализация наследования не поддерживается. Компания Microsoft считает, что множественное наследование ведет к коду, который хуже структурирован и который труднее сопровождать, и поэтому решила исключить это свойство из C#.

Class MyClass : MyBaseClass {

 // и т.д.

В C++ указатель на класс может дополнительно указывать на экземпляр производного класса. (Виртуальные функции в конце концов зависят от этого факта.) В C# классы доступны через ссылки, но правило остается тем же. Ссылка на класс может ссылаться на экземпляры этого класса или на экземпляры любого производного класса.

MyBaseClass Mine;

Mine = new MyClass; // все нормально, если MyClass будет производным

// от MyBaseClass

Если желательно, чтобы ссылка ссылалась на произвольный объект (эквивалент

void*
в C++), можно определить ее как
object
в C#, так как C# отображает
object
в класс
System.Object
, из которого выводятся все другие классы.

object Mine2 = new MyClass;

Виртуальные и невиртуальные функции

Виртуальные функции поддерживаются в C# таким же образом, как и в C++. Однако в C# существуют некоторые синтаксические отличия, которые созданы, чтобы исключить возможную неоднозначность в C++. Это означает, что некоторые типы ошибок, которые появляются в C++ только во время выполнения, будут идентифицированы в C# во время компиляции.

Отметим также, что в C# классы всегда доступны по ссылке (что эквивалентно доступу через указатель в C++).

Если в C++ требуется, чтобы функция была виртуальной необходимо просто определить ключевое слово

virtual
в базовом и производном классах. В противоположность этому в C# необходимо объявить функцию как
virtual
в базовом классе и как
override
в версиях производных классов.

class MyBaseClass {

 public virtual void DoSomething(int X) {

// и т.д.

 }

 // и т.д.

  • Читать дальше
  • 1
  • ...
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: