При анализе пользовательского ввода обычно рекомендуется не генерировать и перехватывать исключения, а использовать методы проверки. В .NET BCL это будет разница между, например, int.Parse
(создает исключение для недопустимых данных) и int.TryParse
(возвращает false
недопустимые данные).
Я создаю свой собственный
Foo.TryParse(string s, out Foo result)
метод, и я не уверен насчет возвращаемого значения. Я мог бы использовать bool
как собственный TryParse
метод .NET , но это не дало бы указание на тип ошибки, на точную причину, почему s
не может быть проанализирован в Foo
. (Например, s
может иметь несоответствующие скобки, или неправильное количество символов, или Bar
без соответствующего Baz
и т. Д.)
Как пользователь API, я сильно не люблю методы, которые просто возвращают логическое значение успеха / неудачи, не сообщая мне, почему операция не удалась. Это делает отладку игрой в догадки, и я не хочу навязывать это клиентам моей библиотеки.
Я могу придумать много обходных путей для этой проблемы (вернуть коды состояния, вернуть строку ошибки, добавить строку ошибки в качестве параметра out), но у них у всех есть свои недостатки, и я также хочу оставаться в соответствии с соглашениями .NET Framework .
Таким образом, мой вопрос заключается в следующем:
Существуют ли в .NET Framework методы, которые (а) анализируют ввод без выдачи исключений и (б) все же возвращают более подробную информацию об ошибках, чем простое логическое значение true / false?
источник
Parse()
.Ответы:
Я бы порекомендовал использовать шаблон монады для вашего типа возврата.
ParseResult<Foo> foo = FooParser.Parse("input");
Также обратите внимание, что Foo не должен выяснять, как его следует анализировать с пользовательского ввода, так как это напрямую связывает ваш уровень домена с уровнем UI, а также нарушает принцип единственной ответственности.
Вы также можете сделать класс результата разбора специфичным
Foo
вместо использования обобщений, в зависимости от вашего варианта использования.Класс результата анализа foo может выглядеть примерно так:
Вот версия Monad:
Я не знаю ни одного метода в .net Framework, который возвращает подробную информацию об ошибке разбора.
источник
Foo.ToString
иFoo.Parse
.Func<T>
будет соответствовать этим критериям, если вы включите вT
необходимую информацию. Возвращение подробной информации об ошибке в значительной степени зависит от вас. Вы рассматривали возможность использованияMaybe<T>
? Смотрите mikhail.io/2016/01/monads-explained-in-csharpВы можете посмотреть на ModelState в рамках MVC. Он представляет собой попытку анализа некоторого ввода и может содержать набор ошибок.
Тем не менее, я не думаю, что есть повторяющийся шаблон для этого в .net BCL, так как исключения - к лучшему или худшему - установленный шаблон для сообщения об ошибках в .net. Я думаю, что вы должны просто пойти дальше и реализовать свое собственное решение, соответствующее вашей проблеме, например,
ParseResult
класс с двумя подклассами,SuccessfulParse
иFailedParse
, гдеSuccessfulParse
имеет свойство с анализируемым значением иFailedParse
свойство сообщения об ошибке. Объединение этого с сопоставлением с образцом в C # 7 может быть довольно элегантным.источник
Я столкнулся с похожими проблемами, связанными с желанием использовать
TryParse/Convert/etc.
метод, в котором мне иногда нужно знать, как и почему это не удалось.Я получил вдохновение от того, как некоторые сериализаторы обрабатывают ошибки и используют события. Таким образом, синтаксис для моего
TryX(..., out T)
метода выглядит таким же чистым, как и любой другой, и надежно возвращает простой,false
как предполагает шаблон.Однако, когда мне нужно больше подробностей, я просто добавляю обработчик событий и получаю все необходимые результаты в пакете, настолько сложном или простом, насколько я хочу (
MyEventArgs
ниже). Добавьте его в список строк, добавьтеExceptionDispatchInfo
и запишите исключения; пусть вызывающий абонент решит, если и как он хочет справиться с чем-то, что пойдет не так.источник