Подтвердить что ты не робот

Различение типов исключений .NET

Для любви ко всем святым, как вы различаете разные "исключения" в предопределенных классах .NET?

Например, кусок кода может вызывать XmlException при следующих условиях:

  • Корневой элемент документа равен NULL
  • Недопустимые символы в документе
  • Документ слишком длинный

Все они выбрасываются как объекты XmlException, а все внутренние поля "расскажите больше об этом исключении" (например, Exception.HResult, Exception.Data и т.д.) обычно пусты или нуль.

Это оставляет Exception.Message как единственное, что позволяет вам различать эти типы исключений, и вы не можете действительно зависеть от него, потому что, как вы догадались, строка Exception.Message glocabilized и может измениться, когда изменения культуры. По крайней мере, что я прочитал в документации.

Exception.HResult и Exception.Data широко игнорируются в библиотеках .NET. Это красноглазый падчерицы мира .NET код обработки ошибок. И даже если предположить, что они не были, тип HRESULT по-прежнему является наихудшим, самым неприличным кодом ошибки в истории кодов ошибок. Почему мы все еще смотрим на HRESULT в 2010 году вне меня. Я имею в виду, если вы делаете Interop или P/Invoke, это одна вещь, но... HRESULTs нет места в System.Exception. HRESULT - бородавка на хоботке System.Exception.

Но серьезно, это означает, что мне нужно настроить множество подробных конкретных ошибок обработки кода, чтобы выяснить ту же информацию, которая должна была быть передана как часть данных исключения. Исключения бесполезны, если они заставляют вас работать так. Что я делаю неправильно?

ИЗМЕНИТЬ. ДЕНЬ ПОЗЖЕ.

Спасибо за все комментарии и отзывы. Я изучаю общий урок здесь ( "сообщения об ошибках сосут" ), даже если я не совсем решил конкретную проблему. Вот конкретный сценарий, с которым я делюсь.

В нашем приложении используются XML файлы, создаваемые третьей стороной. Эти XML файлы иногда содержат незаконные символы, которые действительно не имеют бизнес в XML файле. Эти незаконные символы заставляют (проверять) XmlReader взорвать "незаконное char исключение строки X". Однако мы должны обрабатывать эти файлы, мы не можем просто сказать пользователю, "извините, этот файл не работает 't соответствуют официальной спецификации XML." Наши пользователи даже не знают, что такое XML.

У Microsoft есть официальная (и довольно странная для меня) рекомендация в этом случае (случай, когда XML-документ содержит недопустимые символы): для загрузки файла в поток, итерации к конкретной строке, содержащей ошибку (как предусмотрено, по иронии судьбы, в объекте XmlException) и настраивать замену оскорбительного char на юридический. Затем попробуйте снова загрузить документ в проверяющий XmlReader и посмотреть, не взорвется ли он. Здесь статья базы знаний, описывающая технику.

Так хорошо, мы это делаем, и он работает достаточно хорошо. Проблема в том, что иногда эти XML файлы, которые мы получаем, порождаются другими способами: они могут быть пустыми, могут отсутствовать закрывающий тег и т.д. Поэтому, если вы будете следовать рекомендациям MS, вы фактически зацепите "замену незаконных символов", логику в блок catch, где вы поймаете исходное исключение, созданное проверяющим читателем.

Это прекрасно, если исключение на самом деле является "незаконным char" исключением. Но если это исключение "корневой элемент отсутствует" или "отсутствующий закрывающий тег", вы обнаружите, что метод MS входить и заменять сам оскорбительный char сам взорван, потому что не только не существует оскорбительного char, там вообще не являются символами, или есть, но они являются неверно сформированным XML или что-то еще. На этом этапе вы находитесь в двунаправленном улове внутри, у вас волосы становятся серыми и выпадают, ваши глаза красно-красные с усталостью от кофеина, и вы ставите под сомнение здравомыслие, не говоря уже об утилите используя проверку читателей на основе реального XML.

Итак, мне нужен способ сообщить в блоке начального catch (XmlException), является ли это "корневым элементом отсутствует" или "недопустимым char", поэтому я могу предпринять соответствующие действия. Одна вещь, которую мы не можем сделать, - это запретить нашим пользователям открывать документ, содержащий несколько недопустимых символов. Мы должны обрабатывать эти документы независимо, и я думаю, что это похоже на единственное решение состоит в том, чтобы перебирать все char в документе заблаговременно, рассматривая его как текстовый поток, а не как XML, находить незаконные символы, заменять их, затем загрузите вещь с помощью проверочного XmlReader, и если она взорвется, мы знаем, что это не незаконное исключение char, потому что мы заранее лишили незаконные символы.

Прежде чем сделать это, я подумал, что, по крайней мере, спрошу: 1) можем ли мы получить лучшую информацию из объекта XmlException, и я надеялся, что кто-нибудь скажет мне 2) "все в порядке, чтобы отменить строку XmlException.Message. он локализован, но это не так. Эта строка будет одинаковой для всех версий и культур Windows".

Но никто мне этого не сказал.

4b9b3361

Ответ 1

Я полностью согласен с вами в принципе, но количество случаев, когда я действительно забочусь о том, какая именно причина была выбрана (в моем коде), довольно мала.

Используя XmlException в качестве примера, действительно ли существует какое-то другое поведение, которое у вас было бы в коде, если бы документ был слишком длинным или если у него были недопустимые символы?

Единственный пример, который я могу вспомнить о том, где я когда-либо действительно заботился, - это исключения SQL-типа, где некоторые ошибки могут быть восстановлены (например, потерянное соединение с базой данных).

ETA:

Если вы беспокоитесь о культуре при отключении сообщения об ошибке, вы можете просто установить текущую культуру потока в культуру инвариантов, пока вы обрабатываете документ, а затем установите его обратно в исходную культуру, когда вы закончите. Это должно гарантировать, что сообщение всегда будет одинаковым.

Ответ 2

Проблема здесь кажется плохим сообщением, которое вы получаете от XmlException. Это проблема проектирования API.

Опция использует либо другую библиотеку, чем System.Xml, например System.Xml.Linq, и использует XDocument, чтобы узнать, есть ли у вас лучший код ошибки.

Если ни одна из этих функций не работает, вы можете использовать Open XML Xars Parser, например NDigester и изменить код, чтобы дать более подробную информацию ошибка.

Ответ 3

Похоже на то, что нужна процедура разбора XML, которая вместо того, чтобы бросать исключение при возникновении ошибки синтаксического анализа, вместо этого вызывает делегированный делегат. Если делегат принимает информацию, связанную с состоянием синтаксического анализа, он может попытаться выполнить любые исправления и вернуть значение, указывающее, что оскорбительная часть файла должна быть переоценена.

Конструкция хорошего интерфейса делегата (набор параметров и соглашение о вызовах) для таких целей может быть сложной задачей, но такая система может значительно более эффективно пробивать себе путь через поврежденные файлы, чем тот, который генерирует исключение.