Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
GEK / ООП_ГОСЫ_ОТВЕТЫ.docx
Скачиваний:
68
Добавлен:
18.05.2015
Размер:
1.83 Mб
Скачать

Вызов базовых версий методов

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

public class CustomerAccount

{

public virtual decimal CalculatePrice (CustomerAccount account)

{

// ...

return 2000M;

}

}

public class GoldAccount : CustomerAccount

{

public override decimal CalculatePrice(CustomerAccount account)

{

return base.CalculatePrice(account) * 0.9M;

}

}

+ Индексаторы, операции, свойства можно делать виртуальными и перекрывать их по желанию.

+ Поля не могут быть объявлены виртуальными или перекрытыми. Однако можно скрыть базовую версию поля, объявив другое поле с тем же именем в производном классе с модификатором (new). Получить доступ к базовому полю можно через base.[имя_поля].

+ Статические методы не могут быть объявлены виртуальными, но могут быть скрытыми (new). Не имеет смысла объявлять виртуальным статический член вообще!

  1. Обработка исключений. Привести примеры кода на одном из объектно-ориентированных языков C++,JavaилиC#.

В языке C# ошибки в программе во время выполнения передаются через программу посредством механизма, называемого исключениями. Исключения создаются кодом, который встречает ошибку и перехватываются кодом, который может исправить ее. Исключения могут создаваться средой CLR платформы .NET Framework или кодом в программе. В случае исключения, оно передается по стеку вызовов пока не будет найден оператор catch для исключения. Не перехваченные исключения обрабатываются универсальным обработчиком исключений, предоставляемым системой, который открывает диалоговое окно.

Исключения представляются посредством классов, производных от Exception. Такой класс устанавливает тип исключения и содержит свойства с подробными сведениями об исключении. При генерации исключения создается экземпляр класса, производного от исключения, настраиваются свойства исключения (необязательно), а затем при помощи ключевого слова throw создается объект. Например:

C#

Копировать

class CustomException : Exception

{

public CustomException(string message)

{

}

}

private static void TestThrow()

{

CustomException ex =

new CustomException("Custom exception in TestThrow()");

throw ex;

}

После генерации исключения среда выполнения проверяет текущий оператор и устанавливает, находится ли он в блоке try. Все блоки catch (если они имеются), связанные с блоком try, проверяются на возможность обработать исключение. В блоках Catch обычно задаются типы исключений; если тип блока catch совпадает с типом исключения или базовым классом исключения, то блок catch может обработать данный метод. Например:

C#

Копировать

static void TestCatch()

{

try

{

TestThrow();

}

catch (CustomException ex)

{

System.Console.WriteLine(ex.ToString());

}

}

Если оператор, создающий исключение, расположен вне блока try или если блок try, в котором он расположен, не имеет соответствующего блока catch, среда выполнения проверяет вызывающий метод на наличие оператора try и блоков catch. Время выполнения продолжается до вызывающего стека в поисках совместимого блока catch. После того, как блок catch найден и выполнен, управление передается следующему оператору после того блока catch.

Оператор try может содержать несколько блоков catch. Выполняется первый оператор catch, который может обработать исключение; все последующие операторы catch, даже если они совместимы – пропускаются. Поэтому необходимо, чтобы блоки catch всегда были упорядочены в порядке от более конкретных (или замыкающих цепочку наследования) к более общим. Например:

C#

Копировать

static void TestCatch2()

{

System.IO.StreamWriter sw = null;

try

{

sw = new System.IO.StreamWriter(@"C:\test\test.txt");

sw.WriteLine("Hello");

}

catch (System.IO.FileNotFoundException ex)

{

// Put the more specific exception first.

System.Console.WriteLine(ex.ToString());

}

catch (System.IO.IOException ex)

{

// Put the less specific exception last.

System.Console.WriteLine(ex.ToString());

}

finally

{

sw.Close();

}

System.Console.WriteLine("Done");

}

Перед выполнением блока catch среда выполнения проверяет наличие блоков finally. Блоки Finally позволяют программисту очищать любое неоднозначное состояние, которое могло быть оставлено прерванным блоком try, или освобождать любые внешние ресурсы (например, обработчики графики, подключения к базам данных или потоки файлов), не дожидаясь сборки мусора во время выполнения для завершения объектов. Например:

C#

Копировать

static void TestFinally()

{

System.IO.FileStream file = null;

//Change the path to something that works on your machine.

System.IO.FileInfo fileInfo = new System.IO.FileInfo(@"C:\file.txt");

try

{

file = fileInfo.OpenWrite();

file.WriteByte(0xF);

}

finally

{

// Closing the file allows you to reopen it immediately - otherwise IOException is thrown.

if (file != null)

{

file.Close();

}

}

try

{

file = fileInfo.OpenWrite();

System.Console.WriteLine("OpenWrite() succeeded");

}

catch (System.IO.IOException)

{

System.Console.WriteLine("OpenWrite() failed");

}

}

Если WriteByte() сгенерировал исключение, код во втором блоке try, пытающийся повторно открыть файл, не будет выполнен, если file.Close() не вызван, и файл останется заблокированным. Так как блоки finally выполняются даже в случае генерации исключения, блок finally в предыдущем примере предусматривает правильное закрытие файла и помогает избежать ошибок.

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

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

  • Если в стеке вызовов содержится статический конструктор или статический инициализатор поля, генерируется TypeInitializationException и исходное исключение присваивается свойству InnerException нового исключения.

  • По достижении начала потока он прерывается.

Блок try используется программистами C# для разбиения на разделы кода, который может затрагиваться исключением. Связанные с ним блоки поймать используются для обработки возможных исключений. Блок finally, содержащий код, выполняемый вне зависимости от того, вызвано ли исключение в блоке try, например освобождение ресурсов, выделенных блоку try. Блоку try требуется один или несколько связанных блоков catch или блок finally (либо и то, и другое).

Следующие примеры показывают операторы try-catch, try-finally и try-catch-finally.

C#

Копировать

try

{

// Code to try goes here.

}

catch (SomeSpecificException ex)

{

// Code to handle the exception goes here.

// Only catch exceptions that you know how to handle.

// Never catch base class System.Exception without

// rethrowing it at the end of the catch block.

}

C#

Копировать

try

{

// Code to try goes here.

}

finally

{

// Code to execute after the try block goes here.

}

C#

Копировать

try

{

// Code to try goes here.

}

catch (SomeSpecificException ex)

{

// Code to handle the exception goes here.

}

finally

{

// Code to execute after the try (and possibly catch) blocks

// goes here.

}

Блок try без блока catch или блока finally вызовет ошибку компилятора.

Блоки catch

Блок catch может указывать тип перехватываемого исключения. Спецификация типа называется фильтр исключений. Тип исключения должен быть унаследован от Exception. Как правило, не следует задавать Exception в качестве фильтра исключений, кроме случаев, когда известно, как обрабатывать все исключения, которые могут быть созданы в блоке try, и когда оператор throw вставлен в конце блока catch.

Несколько блоков catch с различными фильтрами исключений могут быть указаны последовательно. Блоки catch проверяются сверху вниз в коде, однако для каждого вызванного исключения выполняется только один блок catch. Выполняется первый блок catch, указывающий точный тип или базовый класс созданного исключения. Если нет блока catch, который определяет соответствующий фильтр исключений, выбирается блок catch, в котором не выбран фильтр, если таковой имеется в операторе. Очень важно, чтобы первыми были размещены блоки catch с самыми конкретными (т. е., самыми производными) типами исключений.

Перехват исключений возможен при выполнении следующих условий.

  • Имеется хорошее понимание причин создания исключения, существует возможность реализовать конкретное восстановление, например предложить пользователю ввести новое имя файла при перехвате объекта FileNotFoundException.

  • Возможность создания и вызова нового, более конкретного исключения.

C#

Копировать

int GetInt(int[] array, int index)

{

try

{

return array[index];

}

catch(System.IndexOutOfRangeException e)

{

throw new System.ArgumentOutOfRangeException(

"Parameter index is out of range.");

}

}

  • Требуется частично обработать исключение перед передачей его на дополнительную обработку. В следующем примере блок catch используется для добавления записи в журнал ошибок перед повторным вызовом исключения.

C#

Копировать

try

{

// Try to access a resource.

}

catch (System.UnauthorizedAccessException e)

{

// Call a custom error logging procedure.

LogError(e);

// Re-throw the error.

throw;

}

Блоки finally

Блок finally позволяет завершить обработку действий, выполненных в блоке try. При наличии блока finally он выполняется последним, после блока try и всех выполняемых блоков catch. Блок finally выполняется всегда, вне зависимости от возникновения исключения или обнаружения блока catch, соответствующего типу исключения.

Блок finally можно использовать для высвобождения ресурсов, например потоков данных, подключений к базам данных, графических дескрипторов, не ожидая финализации объектов сборщиком мусора в среде выполнения. Дополнительные сведения см. в разделе Оператор using (Справочник по C#).

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

C#

Копировать

System.IO.FileStream file = null;

System.IO.FileInfo fileinfo = new System.IO.FileInfo("C:\\file.txt");

try

{

file = fileinfo.OpenWrite();

file.WriteByte(0xF);

}

finally

{

// Check for null because OpenWrite might have failed.

if (file != null)

{

file.Close();

}

}

Исключения позволяют обозначить, что во время выполнения программы произошла ошибка. Объекты исключений, описывающие ошибку, создаются и затем генерируются с ключевым словом throw. Далее во время выполнения происходит поиск наиболее совместимого обработчика исключений.

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

  • Метод не способен выполнить свои определенные функции.

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

C#

Копировать

static void CopyObject(SampleClass original)

{

if (original == null)

{

throw new System.ArgumentException("Parameter cannot be null", "original");

}

}

  • На основе состояния объекта выполнен неправильный вызов объекта.

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

C#

Копировать

class ProgramLog

{

System.IO.FileStream logFile = null;

void OpenLog(System.IO.FileInfo fileName, System.IO.FileMode mode) {}

void WriteLog()

{

if (!this.logFile.CanWrite)

{

throw new System.InvalidOperationException("Logfile cannot be read-only");

}

// Else write data to the log and return.

}

}

  • Когда исключение вызывает аргумент метода.

В этом случае, должно быть перехвачено исходное исключение и создан экземпляр ArgumentException. Исходное исключение должно быть передано конструктору ArgumentException в качестве параметра InnerException:

C#

Копировать

static int GetValueFromArray(int[] array, int index)

{

try

{

return array[index];

}

catch (System.IndexOutOfRangeException ex)

{

System.ArgumentException argEx = new System.ArgumentException("Index is out of range", "index", ex);

throw argEx;

}

}

Исключения содержат свойство с именем StackTrace. Строка содержит имя методов в текущем стеке вызовов вместе с именем файла и номером строки, в которой было сгенерировано исключение для каждого метода. Объект StackTrace создается автоматически средой CLR из точки оператора throw, так что исключения должны генерироваться из той точки, где должна начинаться трассировка стека.

Все исключения содержат свойство с именем Message. Эта строка должно содержать сообщение с объяснением причин исключения. Обратите внимание, что секретные сведения не следует помещать в текст сообщения. Кроме Message, ArgumentException содержит свойство с именем ParamName, которому необходимо присвоить имя аргумента, вызвавшего генерацию исключения. В случае с установщиком свойств, свойству ParamName должно быть присвоено значение value.

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

Чего следует избегать при генерации исключений

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

  • Исключения не рекомендуется использовать для изменения потока программы в рамках обычного выполнения. Исключения используются только для сообщения о состояниях ошибки и их обработки.

  • Исключения не должны возвращаться в качестве возвращаемого значения или параметра вместо генерации.

  • Не рекомендуется специально генерировать System.Exception, System.SystemException, System.NullReferenceException или System.IndexOutOfRangeException из собственного исходного кода.

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

Определение классов исключений

Программы могут генерировать предопределенный класс исключений в пространстве имен System (если специально не обозначено иное), или создавать собственные классы исключений путем наследования от Exception. Производные классы должны определять, по меньшей мере, четыре конструктора: один конструктор по умолчанию, один конструктор, задающий свойство сообщения, и еще один, задающий свойства Message и InnerException. Четвертый конструктор служит для сериализации исключения. Новые классы исключений должны быть сериализуемыми. Например:

C#

Копировать

[Serializable()]

public class InvalidDepartmentException : System.Exception

{

public InvalidDepartmentException() : base() { }

public InvalidDepartmentException(string message) : base(message) { }

public InvalidDepartmentException(string message, System.Exception inner) : base(message, inner) { }

// A constructor is needed for serialization when an

// exception propagates from a remoting server to the client.

protected InvalidDepartmentException(System.Runtime.Serialization.SerializationInfo info,

System.Runtime.Serialization.StreamingContext context) { }

}

Новые свойства следует добавлять к классу исключений только в том случае, если данные в них могут помочь в разрешении исключения. При добавлении новых свойств в производный класс исключений, ToString() должно быть перезаписано для возврата добавленных сведений.

Некоторые исключения автоматически создаются средой CLR приложения платформы .NET Framework, когда происходит сбой основной операции. Эти исключения и условия их возникновения перечислены в следующей таблице.

exception

Описание

ArithmeticException

Основной класс исключений, происходящих при выполнении арифметических операций, таких как DivideByZeroException и OverflowException.

ArrayTypeMismatchException

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

DivideByZeroException

Создается при попытке разделить целое число на ноль.

IndexOutOfRangeException

Создается при попытке индексирования массива, если индекс меньше нуля или выходит за границы массива.

InvalidCastException

Создается, когда происходит сбой явного преобразования из основного типа в интерфейс либо в производный тип во время выполнения.

NullReferenceException

Создается при попытке ссылки на объект, значение которого равно null.

OutOfMemoryException

Создается при неудаче попытки выделения памяти с помощью оператора new. Это означает, что память, доступная для среды выполнения, уже исчерпана.

OverflowException

Создается при переполнении арифметической операции в контексте checked.

StackOverflowException

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

TypeInitializationException

Создается, когда статический конструктор создает исключение, и не существует ни одного совместимого предложения catch для его захвата.

  1. Область видимости и модификаторы доступа. Привести примеры кода на одном из объектно-ориентированных языков C++,JavaилиC#.

Соседние файлы в папке GEK