Comments 11
Необходимость в типизации исключений, как мне кажется, опирается на различение сценариев их обработки. Многократно видел в проектах избыточно используемые классы исключений, которые имеют единый сценарий обработки. В текущем проекте multi-catch блок используется в единственном месте, реализует различную логику при ошибке авторизации и других типах исключений.
Использование единого реестра кастомных исключений (если они нужны) выглядит интересным решением.
Да, единый реестр исключений это не только более эффективно по производительности, но и более красиво.
Обычно я создаю статический класс Errors
и помещаю туда все выбрасываемые исключения. Код, который создаёт текст исключения, закономерно переходит туда же. В результате мы получаем более чистый код в месте выбрасывания исключения.
У меня только один вопрос-просьба: в каких реальных, а не синтетических кейсах затраты на throw оказались настолько критичными, что потребовалась оптимизация? Приведите пример, пожалуйста
а зачем выбрасывать исключение из статического метода, тем самым нарушая анализ точек выхода в компилятре/IDE (см. пример кода по ссылке RavenDB где return после вызова метода Throw..)? почему бы не вернуть исключение (интерфейс Throwable), а ключевое слово throw оставить на месте вызова статического метода? тем самым сделав эти методы статическими методами-фабриками для исключений.
Цель подобных трюков как раз в том, чтобы обмануть компилятор и попытаться заинлайнить метод. Вообще, все микрооптимизации не про красивый код, а про то, чтоб добиться производительности.
Однако, в данном конкретном случае я в версию инлайна верю слабо. Скорее тут это сделано для единообразия кода.
Тут смысл как раз в том, что throw
генерирует кучу бойлерплейта вокруг себя, так что метод, где используется throw
, уже может не получиться заинлайнить. Вынося же throw
в отдельный метод, мы оставляем весь бойлерплейт внутри этого отдельного метода, а всё остальное прекрасно инлайнится.
Привет! Спасибо за интересную и познавательную статью. Всем, конечно хороши методы-хелперы выбрасывающие исключения, но у них есть один недостаток, в языке C# нельзя указать, что метод выбрасывает исключение, т.о. при использовании методов-хелперов, после них, далее по коду появляются предупреждения о например, использовании неинициализированных переменных или другие предупреждения, которых бы не было при явном использовании throw. Вопрос: а существует ли какой-нибудь атрибут в том же Решарпере, например, который будучи применен к методу-хелперу, "успокоил" бы компилятор, что бы он "думал", что этом обычный выброс исключения и генерировал бы описанные выше предупреждения?
Да, знакомая ситуация. И, увы, нет, я не знаю никаких способов это победить. Приходится ставить восклицательные знаки там, где я точно знаю, что не null.
Начиная с .Net Core 3.0 появились атрибуты DoesNotReturn
и DoesNotReturnIf
, правда, к сожалению, они влияют только на nullable-анализ. Так что делать return
после вызова методов всё равно нужно…
На сколько понял, вот тут описано, как такое можно реализовать. (Сам не пробовал)
https://www.jetbrains.com/help/resharper/Contract_Annotations.html#syntax
Inline и throw