Почему C # не поддерживает фильтрацию исключений первого прохождения?

StackOverflow https://stackoverflow.com/questions/602066

  •  03-07-2019
  •  | 
  •  

Вопрос

Примечание:это не дубликат вопроса Джеффа.

На этот вопрос был задан вопрос "Есть ли эквивалент?" Я знаю, что его нет, и я хочу знать почему!

Причина, по которой я спрашиваю, заключается в том, что мне только сейчас стало ясно, насколько это важно, и вывод кажется мне очень странным.

Блок обработки исключений корпоративной библиотеки Microsoft рекомендует нам использовать этот шаблон:

catch (Exception x)
{
    if (ExceptionPolicy.HandleException(x, ExceptionPolicies.MyPolicy))
        throw;

    // recover from x somehow
}

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

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

Между тем, команда CLR в MS говорит, что это не вариант, и оказывается, что эти ребята знают, о чем говорят!Проблема в том, что прямо перед catch блоковые прогоны, любые finally блоки, вложенные внутри try блок будет выполнен.Итак, эти finally блоки могут выполнять любое из следующих действий:

  • Безвредно изменяйте состояние программы (фух, повезло).
  • Выбросьте что-то важное из данных клиента, потому что состояние программы испорчено до неизвестной степени.
  • Замаскируйте или уничтожьте важные доказательства, необходимые нам для диагностики проблемы, особенно если мы говорим о вызовах машинного кода.
  • Бросок другой исключение, усугубляющее общую неразбериху и нищету.

Обратите внимание , что using оператор и деструкторы C ++ / CLI построены на try/finally, так что они тоже затронуты.

Так ясно, что catch/throw шаблон для фильтрации исключений никуда не годится.Что на самом деле необходимо, так это способ фильтрации исключений с помощью политики, фактически не перехватывая их и, таким образом, не запуская выполнение finally блокируется, если только мы не найдем политику, которая сообщает нам, что исключение безопасно для восстановления.

Команда CLR недавно написала об этом в блоге:

В результате нам приходится писать вспомогательную функцию в VB.NET, чтобы получить доступ к этой жизненно важной возможности из C #.Главный признак того, что проблема существует, заключается в том, что в BCL есть код, который это делает.Многие люди писали в блогах об этом, но они редко, если вообще когда-либо упоминают об этом try/finally блоки, которые и есть убийца.

Что я хотел бы знать, так это:

  • Есть ли какие-либо публичные заявления или прямые электронные письма, которые люди получили от команды C # по этому вопросу?
  • Существуют ли какие-либо существующие предложения Microsoft Connect с просьбой об этом?До меня доходили слухи о них, но ни одно из вероятных ключевых слов ничего не выявило.

Обновить: как отмечалось выше, я уже искал в Microsoft Connect, но ничего не нашел.Я также (что неудивительно) погуглил.Я всего лишь нашел людей объясняющие, зачем им нужна эта функция, или указывая на преимущества этого в VB.NET, или бесплодно надеясь , что это будет добавлено в будущей версии C#, или работаем над этим, И множество вводящий в заблуждение совет.Но никакого заявления о причинах исключения этого из всех текущих версий C # нет.И причина, по которой я спрашиваю о существующих проблемах с подключением, заключается в том, что (а) я не создаю ненужный дубликат и (б) я могу сообщить заинтересованным людям, если мне придется его создать.

Обновление 2: Найденный интересная старая запись в блоге Эрика Ганнерсона, ранее работал в команде C #:

"Да, возможность поставить условие для catch несколько удобнее , чем писать тест самостоятельно, но на самом деле это не позволяет вам делать что-то новое".

Это было то же самое предположение, которое было у меня, пока мне не объяснили его должным образом!

Это было полезно?

Решение

Что касается любых существующих ошибок подключения.Следующий выпуск посвящен летающим исключениям.Пользователь явно не указал, что хочет, чтобы они были фактическим фильтром в смысле того, когда они выполняются, но, ИМХО, это подразумевается логикой.

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx ?Идентификатор обратной связи=401668

Однако, помимо этой проблемы, я не могу найти или узнать о каких-либо проблемах, связанных с тем, что вы ищете.Я думаю, было бы неплохо иметь отдельную проблему, которая явно указывает на необходимость использования VB.Фильтры исключений в сетевом стиле.

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

Что касается части получения официального ответа от команды C #, вы, скорее всего, получите его, когда либо 1) зарегистрируете ошибку подключения, либо 2) будете обмануты в отношении основной ошибки.Я действительно сомневаюсь, что прямо сейчас есть официальная причина / оправдание.

Вот мой спекуляция по этому вопросу:Я предполагаю, что этой функции просто не было в оригинальном наборе функций C # 1.0, и с тех пор не было достаточного спроса, чтобы внедрить ее в язык.Команда C # и VB тратят невероятное количество времени на ранжирование языковых функций в начале каждого цикла разработки.Мы должны кое-что приготовить очень временами бывают трудные порезы.Без достаточного спроса вероятность того, что функция попадет в язык, очень мала.

До недавнего времени, бьюсь об заклад, вам было бы трудно найти 1 человека из 10, который понимал бы разницу между VB.Net's Try / When и просто использованием простого старого оператора if в блоке catch C #.Кажется, в последнее время это немного больше занимает умы людей, так что, возможно, это войдет в будущую версию языка.

Другие советы

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

Для получения реального ответа на ваш вопрос вам понадобится ответ Андерса Хейлсберга или кого-либо, кто присутствовал на первоначальных совещаниях по дизайну.Вы могли бы попробовать узнать, сможет ли вам задать этот вопрос интервьюер 9 канала в следующий раз собеседование с командой разработчиков C #.

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

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

Если в этом нет ошибки подключения, вы должны ввести ее и предложить другим проголосовать за нее.[Я бы рекомендовал запрашивать доступ к функции CLR, а не пытаться спроектировать, как она вписывается в язык.]

Я тоже не верю, что в Java есть опция фильтрации.Предполагая, что если бы это было так, мы бы увидели такой же в C #.VB.net скорее всего, это произошло случайно, учитывая, что команда VB начала с чистого листа.

Одна вещь, которая может сыграть вам на руку при получении этой опции в будущей версии C #, - это заявленная цель Microsoft поддерживать паритет между функциями laguage в будущих версиях C # и VB.net.Я бы выдвинул свой аргумент, основываясь на этом.

http://www.chriseargle.com/post/2009/01/Parity-Between-Languages.aspx

Что касается первого вопроса, то если было публичное заявление, то оно, скорее всего, было размещено где-то в Интернете, и в этом случае Google должен что-то найти (если оно существует).

Если это прямое электронное письмо с командой C #, то более чем вероятно, что оно находится под NDA, поэтому его все равно нельзя будет опубликовать.

Что касается второго вопроса, то в Microsoft Connect есть функция поиска, которую вам предложат использовать перед вводом нового предложения.Если вы не можете его найти, то, скорее всего, его и нет.

Моя рекомендация состояла бы в том, чтобы внести предложение, а затем продвигать его, чтобы другие оценили его.

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

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

Так что, если я чего-то не понимаю, нет большой выгоды от наличия фильтров исключений, поддерживаемых языком.

Я могу назвать по крайней мере две причины, по которым фильтрация исключений отсутствует в C#

  1. Разрешение фильтров исключений может побудить программистов делать что-то во время обработки исключений первого прохода, что было бы небезопасно в то время, даже если это можно было бы безопасно выполнить в рамках "catch" или "finally".Например, если код в блоке "try" получает блокировку и генерирует исключение, пока блокировка удерживается, блокировка будет удерживаться во время выполнения внешних фильтров исключений, но будет снята перед запуском внешнего блока "catch" или "finally".Кроме того, по крайней мере, в прошлый раз, когда я проверял, исключения, которые возникали в фильтре исключений и не были перехвачены в нем, были молчаливо подавлены - что-то вроде уродливой ситуации.
  2. Разработчики C # стремятся сделать свой язык "не зависящим от фреймворка".Если C # поддерживает фильтрацию исключений .net первого прохождения, программы, использующие эту функцию, могут быть непригодны для использования в платформах, которые обрабатывают исключения по-другому.Это та же причина, по которой C # запрещает программам переопределять `Object.Finalize()`.В то время как рассуждения, связанные с `Object.Finalize()`, ошибочны (правильное использование деструкторов требует использования других методов, зависящих от платформы, поэтому требует использования синтаксиса деструктора для `Object.Finalize()` не выполняет ничего, кроме как t77o поощряет написание дефектного программного обеспечения) рассуждения действительно имеют некоторый смысл в отношении фильтров исключений.С другой стороны, правильным способом решения этой проблемы было бы предоставить некоторые функции, связанные с фильтром исключений, даже если бы вы не предоставляли фильтры исключений напрямую.

Одна функция, которую я бы действительно хотел видеть в C # и vb, для реализации которой потребовалось бы использование фильтров исключений, но которая не требовала бы их прямого раскрытия, была бы необязательной Exception параметр для finally блок.Этот параметр будет равен null если не возникает неперехваченного исключения;в противном случае он содержал бы исключение, о котором идет речь.Это допускало бы ситуации, когда программа захочет что-то сделать при возникновении исключения, но фактически не "обработает" его.В большинстве случаев Exception параметр не будет использоваться ни для чего, кроме как для проверки null (это означает, что функция была бы эквивалентна раскрытию fault блоки), но это дало бы преимущества в случаях, когда во время очистки возникает исключение.В настоящее время, если исключение возникает во время finally блокировать, необходимо либо заглушить finally-заблокировать исключение или перезаписать уже существующее.Наличие более раннего исключения, доступного для finally блочный код позволил бы ему либо обернуть, либо записать его в журнал.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top