Console.WriteLine("P3 and P4 are pointing to same object: {0}",
object.ReferenceEquals(p3, p4));
// Р3 и P4 указывают на тот же самый объект
}
Здесь вы имеете возможность просто отправить два объекта (любого типа) и позволить классу System.Object выяснить детали автоматически. Ниже показан вывод, полученный в результате вызова метода StaticMembersOfObject() в операторах верхнего уровня:
***** Fun with System.Object *****
P3 and P4 have the same state: True
P3 and P4 are pointing to the same object: False
Резюме
В настоящей главе объяснялась роль и детали наследования и полиморфизма. В ней были представлены многочисленные новые ключевые слова и лексемы для поддержки каждого приема. Например, вспомните, что с помощью двоеточия указывается родительский класс для создаваемого типа. Родительские типы способны определять любое количество виртуальных и/или абстрактных членов для установления полиморфного интерфейса. Производные типы переопределяют эти члены с применением ключевого слова override.
Вдобавок к построению множества иерархий классов в главе также исследовалось явное приведение между базовыми и производными типами. В завершение главы рассматривались особенности главного родительского класса в библиотеках базовых классов .NET Core — System.Object.
Глава 7
Структурированная обработка исключений
В настоящей главе вы узнаете о том, как иметь дело с аномалиями, возникающими во время выполнения кода С#, с использованием try, catch, throw, finally, when), но и разница между исключениями уровня приложения и уровня системы, а также роль базового класса System.Exception. Кроме того, будет показано, как создавать специальные исключения, и рассмотрены некоторые инструменты отладки в Visual Studio, связанные с исключениями.
Ода ошибкам, дефектам и исключениям
Что бы ни нашептывало наше (порой завышенное) самомнение, идеальных программистов не существует. Разработка программного обеспечения является сложным делом, и из-за такой сложности довольно часто даже самые лучшие программы поставляются с разнообразными Chucky). Вне зависимости от причин проблемы в конечном итоге приложение не работает ожидаемым образом. Чтобы подготовить почву для предстоящего обсуждения структурированной обработки исключений, рассмотрим три распространенных термина, которые применяются для описания аномалий.
• Дефекты. Выражаясь просто, это ошибки, которые допустил программист. В качестве примера предположим, что вы программируете на неуправляемом C++. Если вы забудете освободить динамически выделенную память, что приводит к утечке памяти, тогда получите дефект.
• Пользовательские ошибки. С другой стороны, пользовательские ошибки обычно возникают из-за тех, кто запускает приложение, а не тех, кто его создает. Например, ввод конечным пользователем в текстовом поле неправильно сформированной строки с высокой вероятностью может привести к генерации ошибки, если в коде не была предусмотрена обработка некорректного ввода.
• Исключения. Исключениями обычно считаются аномалии во время выполнения, которые трудно (а то и невозможно) учесть на стадии программирования приложения. Примерами исключений могут быть попытка подключения к базе данных, которая больше не существует, открытие запорченного XML-файла или попытка установления связи с машиной, которая в текущий момент находится в автономном режиме. В каждом из упомянутых случаев программист (или конечный пользователь) обладает довольно низким контролем над такими "исключительными" обстоятельствами.