Try-catch каждая строка кода без отдельных блоков try-catch - PullRequest
12 голосов
/ 22 сентября 2008

У меня нет этой проблемы , но вы никогда не знаете, и мысленные эксперименты всегда веселые.

Игнорируя очевидные проблемы, которые могут возникнуть у вас с вашей архитектурой, чтобы даже попытаться сделать это , давайте предположим, что у вас был какой-то ужасно написанный код чужого дизайна, и вам нужно было сделать кучу широких и разнообразных операций в одном блоке кода, например:

WidgetMaker.SetAlignment(57);
contactForm["Title"] = txtTitle.Text;
Casserole.Season(true, false);
((RecordKeeper)Session["CasseroleTracker"]).Seasoned = true;

Умножается на сто. Некоторые из них могут работать, другие могут пойти не так, как надо. То, что вам нужно, это эквивалент C # «при возобновлении ошибки далее», в противном случае вы в конечном итоге будете копировать и вставлять пробные уловки вокруг множества строк кода.

Как бы вы попытались решить эту проблему?

Ответы [ 19 ]

1 голос
/ 23 сентября 2008

Если вы можете заставить компилятор предоставить вам дерево выражений для этого кода, тогда вы можете изменить это дерево выражений, заменив каждый оператор новым блоком try-catch, который оборачивает исходный оператор. Это не так надуманно, как кажется; для LINQ C # получил возможность захватывать лямбда-выражения как деревья выражений, которыми можно манипулировать в пользовательском коде во время выполнения.

Этот подход сегодня невозможен в .NET 3.5 - если только по какой-то другой причине, кроме отсутствия оператора "try" в System.Linq.Expressions. Тем не менее, он вполне может быть жизнеспособным в будущей версии C # после завершения слияния деревьев выражений DLR и LINQ.

1 голос
/ 03 августа 2011

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

1 голос
/ 23 сентября 2008

интересный вопрос; очень ужасно.

Было бы неплохо, если бы вы могли использовать макрос. Но это бесполезный C #, так что вы можете решить эту проблему с помощью некоторого препроцессора или какого-либо внешнего инструмента, чтобы обернуть ваши строки в отдельные блоки try-catch. Не уверен, что вы имели в виду, что вы не хотите вручную оборачивать их или что вы хотите избежать try-catch полностью .

Возиться с этим, я попытался пометить каждую строку и отскочить от одного улова, без особой удачи. Однако Кристофер нашел правильный способ сделать это . есть интересное дополнительное обсуждение этого в Dot Net Мысли и Блог Майка Сталла .NET .

РЕДАКТИРОВАТЬ: Конечно. Перечисленное решение try-catch / switch-goto фактически не будет компилироваться, поскольку метки try выходят за рамки catch. Кто-нибудь знает, чего не хватает, чтобы сделать что-то вроде этой компиляции?

Вы можете автоматизировать это с помощью шага препроцессора компилятора или, возможно, взломать Встроенный IL-инструмент Майка Сталла , чтобы внедрить некоторое невежество в отношении ошибок.

( Ответ Ориона Адриана об изучении исключения и попытке установить следующую инструкцию тоже интересен.)

В общем, это кажется интересным и поучительным упражнением. Конечно, вам придется решить, в какой момент усилия по симуляции ON ERROR RESUME NEXT перевешивают усилия по исправлению кода. : -)

1 голос
/ 23 сентября 2008

Вы могли бы использовать goto, но все еще грязно.

Я на самом деле хотел какое-то отдельное выражение try-catch некоторое время. В некоторых случаях это может быть полезно, например, добавление регистрационного кода или что-то, что вы не хотите прерывать основной поток программы в случае сбоя.

Я подозреваю, что с некоторыми функциями, связанными с linq, можно что-то сделать, но на данный момент у меня нет времени на это. Если бы вы могли просто найти способ обернуть оператор в анонимную функцию, используйте другой, чтобы вызвать его в блоке try-catch, он будет работать ... но не уверен, что это возможно, пока.

1 голос
/ 23 сентября 2008

Почему бы не использовать отражение в c #? Вы можете создать класс, который будет отражать код и использовать строки # в качестве подсказки для того, что помещать в каждый отдельный блок try / catch. Это имеет несколько преимуществ:

  1. Это немного менее уродливо, поскольку на самом деле вам не нужно искажать исходный код, и вы можете использовать его только в режимах отладки.
  2. Вы узнаете что-то интересное о c # при его реализации.

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

0 голосов
/ 23 сентября 2008

Выделите каждую строку, одну за другой, «Surround with» try / catch. Это позволяет избежать копирования, о котором вы упоминали

0 голосов
/ 23 сентября 2008

Не обращая внимания на все причины, по которым вы хотите избежать этого .......

Если бы было просто необходимо уменьшить количество строк, вы можете попробовать что-то вроде:

int totalMethodCount = xxx;
for(int counter = 0; counter < totalMethodCount; counter++) {
    try {
        if (counter == 0) WidgetMaker.SetAlignment(57);
        if (counter == 1) contactForm["Title"] = txtTitle.Text;
        if (counter == 2) Casserole.Season(true, false);
        if (counter == 3) ((RecordKeeper)Session["CasseroleTracker"]).Seasoned = true;
    } catch (Exception ex) {
        // log here
    }
}

Однако вам придется следить за переменной областью, если вы попытаетесь повторно использовать любой из результатов вызовов.

0 голосов
/ 23 сентября 2008

Вы можете взглянуть на интеграцию компонента Обработка исключений в Enterprise Library, чтобы узнать, как обрабатывать необработанные исключения.

Если это для приложений ASP.Net, в Global.asax есть функция, называемая «Application_Error», которая вызывается в большинстве случаев, причем обычно случается катастрофический сбой.

0 голосов
/ 23 сентября 2008

К сожалению, вам, вероятно, не повезло. On Error Resume Next - это устаревшая опция, которая, как правило, крайне не рекомендуется и не имеет эквивалента моим знаниям в C #.

Я бы порекомендовал оставить код в VB (похоже, это был источник, учитывая ваш конкретный запрос на OnError ResumeNext) и взаимодействовать с или из C # dll или exe, который реализует любой новый код, который вам нужен. Затем выполните префакторинг рефакторинга, чтобы обеспечить безопасность кода, и при этом конвертируйте этот безопасный код в C #.

...