Всем привет! Сегодня вновь вернёмся к базовым функциям языка C#, но не забудем и про Revit API: в конце вас ждёт интересный код.
Конструкция try-catch-finally позволяет обрабатывать исключения и делать с ними определённые действия. Но давайте сначала разберёмся, что такое исключения и зачем вообще они нужны.
Исключения возникают, когда выполняемый код сталкивается с какой-либо ошибкой. Потенциально это может привести к перегрузке памяти, вылету программы и даже выключению компьютера. Чтобы это не происходило, разработчики пользовательских API предусматривают механизмы создания исключений, и вместо всего вышеописанного мы получаем сообщение, что выполнить указанный код невозможно.
Рассмотрим пример. Напишем код в консольном приложении:
int i = 5;
int j = 0;
i= i / j;
Запустим:
Иногда возникшие случаи бывают сложнее. Например, если написать в классе свойство, ссылающееся на само себя при попытке получения, а затем вызвать его в коде:
Получим переполнение стека и потенциальные ошибки:
Если написать такое в плагине для Revit, то Revit завершится с фатальной ошибкой (можете проверить).
Конструкция try-catch-finally предназначена для перехвата ошибок и их обработки. Рассмотрим синтаксис:
Сначала идёт обязательный блок try. В нём выполняются все инструкции. Если возникло исключение, то выполнение прекращается, и исполняются инструкции блока catch. Если исключение не возникло, то блок catch не выполняется. Блок finally выполняется сразу после этих 2 блоков в любом случае.
Любой из блоков может быть пустым, блок catch можно не писать, а сразу написать finally, но совсем без них нельзя.
Где это можно применять в Revit API
Можно (но не обязательно нужно) применять где угодно: захотели, весь код обернули в try-catch (для отладки), захотели — проверили так наличие параметра. Но я настоятельно так делать не советую.
NullReferenceException
Чаще всего вы будете сталкиваться именно с таким исключением. Когда оно может возникнуть:
- Вы берёте значения параметра, который не найден, и вернул null.
- Вы берёте свойство элемента у свойства, которое вернуло null.
- Вы пытаетесь добавить элемент в список, который не был проинициализирован пустым списком.
List<int> ints = new List<int>(); — инициализировали.
List<int> ints; — не инициализировали.
- Когда угодно.
Бороться с ним лучше всего не конструкцией try-catch, а проверкой на null:
Где нужно применять конструкцию try-catch и это будет уместно и правильно
- При работе с файлами (тут часто бывают исключения: файл может быть недоступен, не существовать, и т.д).
- При работе со сторонним API (отправка данных на сервер и чтение с сервера, запись в Excel и другие варианты).
- При использовании метода PickObject(ObjectType.Element);
(вообще неприятный метод, человек жмёт Esc и вылезает противное сообщение об ошибке, никому не нужное. Нужно просто прервать работу и всё).
- И в других случаях, которых вы посчитаете это оправданным (список может быть не полным — пишите свои варианты в комментарии).
А теперь — обещанный интересный код
Я начинал свою карьеру в строительной отрасли проектировщиком систем противопожарной защиты. Существуют адресные системы пожарной сигнализации: такие системы, где каждый извещатель имеет свой адрес (номер). При срабатывании на экране диспетчера отобразится место возгорания с точностью до помещения и 5-10 м в большом помещении. Удобно
Но вот проектировщику руками нумеровать извещатели очень неудобно. Особенно если по пути в цепь ещё залезли элементы. И автонумераторы не помогут: потому что нумеровать надо вдоль траектории цепи, она может быть с ответвлениями и т.д. Вот бы прощёлкать все элементы и они по очереди пронумеруются...
Встречайте: метод полуавтоматической нумерации в порядке прощёлкивания.
Просто поменяйте ваш префикс, ваше имя параметра и начальное значение в строках 194-195.
Код будет выполняться до тех пор, пока у выбираемых пользователем элементов есть этот параметр, и пока он/она не нажмёт Esc — за это отвечает цикл while. Более того, если элементы будут замаркированы на виде, где выполняется плагин, и в марки будет выведен выбранный параметр, то значения марок будут изменяться прямо на ходу (потому что мы каждый элемент обрабатываем в отдельной транзакции.
4 года назад такой плагин сэкономил бы мне уйму времени. Правда, тогда я бы не смог его установить, не зная статьи по созданию и подключению плагина. Впрочем, точно такой же код можно забить себе и в макросе.
Итоговый код в моём репозитории на GitHub
А на этом всё. Подписывайтесь на мой телеграм-канал, пишите комментарии. До новых встреч!