Почему C# не поддерживает фильтрацию исключений при первом проходе?
Примечание: это не дубликат вопроса Джеффа.
Этот вопрос задал вопрос "Является ли эквивалент?" Я знаю, что нет, и я хочу знать, почему!
Причина, по которой я спрашиваю, состоит в том, что я только что понял, насколько это важно, и заключение кажется мне очень странным.
Блок обработки исключений корпоративной библиотеки 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#:
"Да, возможность поставить условие для улова несколько удобнее, чем писать тест самостоятельно, но на самом деле это не позволяет вам делать что-то новое".
Это было то же предположение, что и у меня, пока оно мне не объяснили!
6 ответов
Что касается любых существующих ошибок подключения. Следующая проблема касается флайтеров исключений. Пользователь явно не заявлял, что хочет, чтобы они были реальным фильтром в том смысле, когда они выполняются, но ИМХО, это подразумевается логикой.
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=401668
Помимо этой проблемы, я не могу найти или узнать о проблемах, связанных с тем, что вы ищете. Я думаю, что было бы хорошо иметь отдельную проблему, которая явно вызывает фильтры для исключений в стиле VB.Net.
Я бы не стал слишком беспокоиться о введении дублирующего вопроса, если вы провели тщательную проверку в поисках уже существующего. Если есть обман, Мадс будет соответственно дублировать его и свяжет вас с основным запросом.
Что касается части получения официального ответа от команды C#, вы, вероятно, получите это, когда вы либо 1) сообщите об ошибке подключения, либо 2) будете обмануты против основной ошибки. Я действительно сомневаюсь, что сейчас существует официальная причина / обоснование.
Вот мое предположение по этому вопросу: я предполагаю, что этой функции просто не было в исходном наборе функций C# 1.0, и с тех пор не было достаточного спроса, чтобы перейти на язык. Команда C# и VB тратит невероятное количество времени на ранжирование языковых функций в начале каждого цикла корабля. Мы должны сделать несколько очень трудных сокращений время от времени. Без достаточного спроса очень мало шансов, что какая-то функция превратится в язык.
До недавнего времени я держал пари, что вам будет трудно найти 1 из 10 человек, которые понимают разницу между Try/When в VB.Net и просто с использованием простого старого оператора if в блоке C# catch. В последнее время кажется, что это немного больше беспокоит людей, так что, возможно, он превратится в будущую версию языка.
Использование фильтра исключения может быть проще, чем использование обходного пути делегата.
Для реального ответа на ваш вопрос вам понадобится ответ от Андерса Хейлсберга или кого-то, кто был на оригинальных совещаниях по дизайну. Вы можете попытаться узнать, можете ли вы спросить об этом у интервьюера Channel 9 в следующий раз, когда группа дизайнеров C# дает интервью.
Я предполагаю, что когда было принято первоначальное решение, фильтры исключений рассматривались как ненужное осложнение, которое могло бы принести больше вреда, чем пользы. В этом интервью вы наверняка увидите желание "молчать" о недоказанных функциях, касающихся решения не поддерживать проверенные исключения: Проблема с проверенными исключениями.
Я думаю, что сценарии постмотермической диагностики настоятельно требуют предоставления доступа к фильтрам исключений в языке. Однако эти сценарии, возможно, не были сформулированы в то время. Кроме того, эти сценарии действительно нуждаются в надлежащей поддержке инструментов, которая, конечно, не была доступна в V1. Наконец, могут быть большие недостатки в добавлении этой функции, которые мы не рассматриваем.
Если в этом нет ошибки подключения, вы должны указать ее и предложить другим проголосовать за нее. [Я бы рекомендовал запрашивать доступ к функции CLR, а не пытаться определить, как она вписывается в язык.]
Я не верю, что у Java есть опция фильтра. Предполагая, что если это произойдет, мы также увидим один в C#. У VB.net, вероятно, есть один случай, учитывая, что команда VB начала с чистого листа.
Одна вещь, которая может работать в вашу пользу, если вы приобретете эту опцию в будущей версии C#, - это заявленная Microsoft цель сохранить паритет между языковыми функциями в будущих версиях C# и VB.net. Я бы выдвинул свои аргументы, основанные на этом.
http://www.chriseargle.com/post/2009/01/Parity-Between-Languages.aspx
Я могу вспомнить хотя бы две причины, по которым фильтрация исключений отсутствует в C#
- Разрешение фильтров исключений может подтолкнуть программистов к действиям во время обработки исключений первого прохода, которые в то время были бы небезопасны, даже если они могли бы быть безопасно выполнены в рамках "catch" или "finally". Например, если код в блоке "try" получает блокировку и выдает исключение, пока блокировка удерживается, блокировка будет удерживаться во время выполнения внешних фильтров исключений, но будет освобождена до внешнего "catch" или "finally". "блок запущен. Кроме того, по крайней мере в прошлый раз, когда я проверял, исключения, которые возникали в фильтре исключений и не попадали в него, были тихо подавлены - что-то вроде уродливой ситуации.
- У разработчиков C# есть видение сделать свой язык независимым от фреймворка. Если C# поддерживает фильтрацию исключений при первом прохождении.net, программы, использующие эту функцию, могут оказаться непригодными для сред, которые по-разному обрабатывают исключения. Это та же самая причина, по которой C# запрещает программам переопределять `Object.Finalize()`. Хотя аргументация вокруг Object.Finalize () `ошибочна (правильное использование деструкторов требует использования других платформо-зависимых методов, поэтому требование использования синтаксиса деструктора для Object.Finalize ()` ничего не дает, кроме t77o, поощряет написание дефектное программное обеспечение) рассуждения имеют некоторый смысл в отношении фильтров исключений. С другой стороны, правильным способом решения этой проблемы было бы раскрытие некоторых функций, связанных с фильтром исключений, даже если один не предоставлял фильтры исключений напрямую.
Одна особенность, которую я действительно хотел бы видеть в C# и vb, которая потребовала бы использования фильтров исключений для реализации, но которая не требовала бы их непосредственного показа, была бы необязательной Exception
параметр для finally
блок. Этот параметр будет null
если не встречается необъяснимое исключение; в противном случае это будет содержать исключение. Это позволило бы в ситуациях, когда программа захочет что-то сделать при возникновении исключения, но на самом деле не "обработать" его. В большинстве случаев Exception
Параметр не будет использоваться ни для чего, кроме как для проверки null
(имеется в виду, что функция будет эквивалентна fault
блоки), но это дало бы преимущества в случаях, когда исключение происходит во время очистки. В настоящее время, если исключение происходит во время finally
блок, нужно либо подавить finally
-Блок исключения или перезаписать ранее существовавший. Наличие более раннего исключения, доступного для finally
блочный код позволил бы или обернуть или зарегистрировать это.
Насколько я понимаю, в момент перезапуска выполняются обработчики finally во внутренних функциях, и это создает проблемы для вас.
Но допустим, что у вас есть фильтр исключений, который пропускает исключение, не перебрасывая его. Вам все равно придется как-то с этим справляться, и вы столкнетесь с такими же проблемами (наконец, с эффектами).
Так что, если я что-то не так понимаю, у меня не будет большой выгоды от наличия поддерживаемых языком фильтров исключений.
Что касается первого вопроса, если было публичное заявление, то оно, скорее всего, было где-то размещено в сети, и в этом случае Google должен что-то поднять (если оно существует).
Если это прямое электронное письмо с командой C#, то, скорее всего, оно находится под NDA, поэтому его нельзя будет опубликовать в любом случае.
Что касается второго вопроса, в Microsoft Connect есть возможность поиска, которую вам предлагают использовать перед вводом нового предложения. Если вы не можете его найти, то, вероятно, его нет.
Моя рекомендация будет заключаться в том, чтобы внести предложение, а затем продвигать его, чтобы другие оценили его.