// код

} // 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) {

  // и т.д.

 }

 // и т.д.

}

class MyClass : MyBaseClass {

 public override void DoSomething(int X) {

  // и т.д.

 }

 // и т.д.

}

Важный момент этого синтаксиса состоит в том, что он дает понять компилятору, как интерпретировать функцию, и значит, исключается риск таких ошибок, где, например, вводится слегка неправильная сигнатура метода в переопределяемой версии, и поэтому определяется новая функция вместо переопределения существующей. Компилятор будет отмечать ошибку, если функция помечена как override, и компилятор не сможет идентифицировать ее версию в каком-либо базовом классе.

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

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

class MyBaseClass {

 public void DoSomething(int X) {

  // и т.д.

 }

 // и т.д.

}

class MyClass : MyBaseClass {

 public new void DoSomething(int X) {

  // и т.д.

 } и т.д.

}

Если не пометить новую версию класса явно как new, то код по-прежнему будет компилироваться, но компилятор будет выдавать предупреждение. Предупреждение служит для защиты от любых трудноуловимых ошибок, возникающих во время выполнения. Например, когда написана новая версия базового класса, в которой добавлен метод, имеющий, оказывается, такое же имя, как и существующий метод в производном классе.

В C# можно объявить абстрактную функцию, также как это делается в C++ (в C++ она называются еще чисто виртуальной функцией), но в C# синтаксис будет отличаться: вместо использования =0 в конце определения применяется ключевое слово abstract.

C++:

public:

 virtual void DoSomething(int X) = 0;

C#:

public abstract void Dosomething(int X);

Как и в C++, можно создать экземпляр класса, только если он сам не содержит абстрактных методов и предоставляет реализации всех абстрактных методов, которые были определены в любом из его базовых

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату