Есть ли название для этого "шаблона"?
мне интересно, есть ли имя для этого "шаблона", где подпись метода называется TrySomething, например int.TryParse
, decimal.TryParse
, etc.
мой коллега часто использует это соглашение об именах - вместо того, чтобы возвращать значение или выбрасывать исключение, они вызовут метод TryDoSomething
и если исключение поймано во время обработки, оно возвращается через out param.
Edit: я понимаю, что пример privided-это не то, как работают методы TryParse. Это было смысл этой публикации... Я не знал, как это назвать. Я согласен, что это больше похоже на соглашение об именах, а не на шаблон. Спасибо за помощь.
Edit:интересные...
рассмотрим шаблон TryParse для членов, которые могут создавать исключения в общих сценариях, чтобы избежать проблем производительности, связанных с исключениями.
чтобы реализовать шаблон TryParse, вы предоставляете два разных метода для выполнения операции, которая может бросьте исключения в общих сценариях. Первый метод, X, выполняет операцию и создает исключение, когда это необходимо. Второй метод TryX не создает исключение, а возвращает логическое значение, указывающее на успех или неудачу. Все данные, возвращенные при успешном вызове TryX, возвращаются с помощью параметра out (ByRef в Visual Basic). Методы Parse и TryParse являются примерами этого шаблона.
8 ответов
Я бы скорее назвал это Ошибка Скрытия Шаблона. Вы получаете выгоду от создания TryX
когда у вас есть код, который обычно создает исключение, которое вместо этого вырезает рано с логическим значением. Если вы посмотрите на методы, предоставляемые платформой, вы заметите TryX
варианты существуют, когда было бы нетривиально или подвержено ошибкам (или так часто это должно быть в рамках), чтобы написать свой собственный IsValidX
метод.
если вы должны поймать исключение, нет смысла обертывать это в метод. Все, что вы делаете, это усложняет отладку проблем ввода. Вместо того, чтобы иметь хорошую трассировку стека для отслеживания сбоя ввода, пользователь может видеть только побочные эффекты неудачного метода. Хуже того, при отладке проблемы разработчик потенциально должен воссоздать тупое состояние программы, чтобы повлиять на режим сбоя.
в принципе, если априори вы знаете операция завершится неудачей с исключением, логично и правильно предоставить компаньона TryX
операции. Это так называемый Тестер-Исполнителем узор. Post hoc анализ операции не Тестер-Исполнителем, а просто Обработка Исключений.
прежде всего, если ваше описание является точным, это не так, как int.TryParse и его братья и сестры работают вообще.
Я признаю, что эти методы немного нарушены, на мой взгляд, поскольку они не передают причину сбоя синтаксического анализа вызывающему абоненту, только то, что он потерпел неудачу. В этом отношении я хотел бы увидеть лучший способ справиться с этим.
на самом деле, лучший способ, опять же, на мой взгляд, был чем-то, что я видел в сторонней библиотеке, которую я не помню, но в основном у них были различные пользовательские типы, которые имели такую пару методов Parse/TryParse, и они сделали следующее:
- определите общую структуру, которая содержит как значение, полученное при разборе строки, так и значение типа перечисления, передающее результат разбора
- все методы TryParse вернули эту структуру и не имели
out
параметр - методы разбора просто называются методами TryParse, а затем переводят различные неудачи результаты этого перечисления в соответствующие исключения
опять же, основная проблема здесь, на мой взгляд, заключалась в том, что она не была расширяемой. Если бы я хотел использовать их систему и типы и добавить свою собственную причину, я бы не смог этого сделать, но некоторые варианты этого легко справились бы с этим.
в любом случае, int.Методы TryParse внутренне не вызывают никаких исключений вообще. Вместо этого они проходят через движения фактического разбора строки, и если они сталкиваются с чем-то они не могут справиться, они просто возвращают false, вот и все, без исключения в игре.
обработка исключений немного дороже, чем альтернатива без исключений, поэтому некоторые такие основные методы оптимизированы для производительности.
вот почему в моем комментарии я назвал ваш шаблон, если он точен, глупым, потому что вы объединили обработку исключений с параметрами out. И что вы можете сделать с этим исключением, как только вы достали ее? бросить? Тогда вы вернемся к началу.
Я бы серьезно посмотрел на ваш шаблон и попытался его изменить.
конечно, все это зависит от предположения, что ваше описание этого является точным.
я называю это "жаль, что у меня Option<T>
" шаблон (который похож на "жаль, что у меня Either<T,E>
" Pattern -- imagine where E : Exception).
TryXYZ (в приведенных выше примерах) имитирует опцию с использованием логического результата и out
paramter. (Для типов значений, это может быть Nullable<T>
в этом случае -- я подозреваю, что это не так для int.TryParse
и друзья частично потому, что Nullable пришел намного позже в .NET). Возврат исключения через out
больше напоминает Любой.
в C# я бы не рекомендовал ловить исключения просто передать их out
параметры в целом, хотя (это " правило "может отличаться от языка, который поддерживает дискриминируемые союзы и сопоставление шаблонов) - я пытаюсь 1) иметь дело с ним" правильно", однако это определено, что очень хорошо мая быть out
на конкретных обстоятельств; или 2) отпустите его, чтобы вызывающий абонент мог попробовать то же самое.
(как уже упоминалось, это скорее условность).
удачи в кодировании.
вы можете назвать это ExceptionSafeBridge
. Он ведет вас из мира исключений в мир кода ошибки. Но я не думаю, что это официально.
эта модель is common, когда вам нужно соединить, например, код C и управляемый код.
дизайн паттернов обычно относится к общей идее, которая является языковым агностиком, поэтому нет, это не шаблон. Это может быть идиома, но, скорее всего, это просто соглашение об именах, как справедливо отметил Аарон в комментарии.
Если проблема возникает во время tryparse, то есть
int val;
if(int.TryParse("2", out val))
{
//do work with val
}
тогда у вас не будет исключения, пойманного через out param, значение 0 для out, false возвращается как логическое значение.
лучше всего использовать "is" или " as " вместо этого.
Я бы не назвал подход, который вы описываете, шаблоном... Просто практика кодирования (не самая лучшая).
пример as:
private void SetObj(object obj)
{
int thisInt = obj as int;
if(thisInt != null)
{
//do work
}
else
{
//handle issue
}
}
выше намного эффективнее во время выполнения, чем пытаться / поймать.
Если вы используете "is", когда as недоступен для вас ("as" не используется для всех типов), не забудьте добавить избыточность, реализуя как с is... используйте только то или другое.