Как возможно возобновить выполнение кода после того, как исключение будет выдано?
Например, возьмите следующий код:
namespace ConsoleApplication1
{
public class Test
{
public void s()
{
throw new NotSupportedException();
string @class = "" ;
Console.WriteLine(@class);
Console.ReadLine();
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
}
catch (Exception ex)
{
}
}
}
}
После ловли исключения при продвижении через, программа прекратит работать. Как я могу все еще продолжить выполнение?
Править: То, что я конкретно имею в виду, является Консолью строки. WriteLine (@class); кажется, не поражен, потому что, когда я работаю к нему, когда в режиме отладки, программа выходит от режима отладки. Я хочу работать к этой строке и остановке в ней.
Спасибо
Ну, у вас нет кода после блоков catch
, поэтому программа остановится. Не уверен, что вы пытаетесь сделать.
Следующее должно быть доказательством того, что программа не просто «останавливается» после блоков catch
. Он выполнит код после блоков catch
, если есть код, который нужно выполнить:
static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
Console.WriteLine("ArgumentException caught!");
}
catch (Exception ex)
{
Console.WriteLine("Exception caught!");
}
Console.WriteLine("I am some code that's running after the exception!");
}
Код напечатает соответствующую строку в зависимости от перехваченного исключения. Затем он напечатает Я - некоторый код, который выполняется после исключения!
в конце.
ОБНОВЛЕНИЕ
В своем редактировании вы спросили, почему Console.WriteLine (@class);
не работает. Причина в том, что вы явно генерируете исключение в самой первой строке вашего метода s ()
; все последующее игнорируется. Когда возникает исключение, выполнение останавливается, и исключение распространяется вверх по стеку вызовов до тех пор, пока соответствующий обработчик не сможет его обработать (это может быть блок catch
, который соответствует try
, который обертывает рассматриваемый оператор в том же методе, или это может быть блок catch
далее вверх по стеку вызовов.Если соответствующий обработчик не найден, программа завершится трассировкой стека (по крайней мере, в Java - не уверен, что то же самое происходит в C #)).
Если вы хотите попасть в строку Console.WriteLine
, вам не следует явно генерировать исключение в начале метода.
Похоже, что вы хотите возобновляемые исключения. В C# нет возобновляемых исключений, и я сомневаюсь, что CLR поддерживает их.
Цель выброса исключения - прервать функцию и всю операцию (стек вызовов), если/когда что-то в окружении вызова (параметры, состояние объекта, глобальное состояние) делает работу функции невозможной или недействительной. Например, передача нулевого параметра функции, которой нужно разделить величину на этот параметр. Деление на ноль не даст осмысленного результата, а если это единственная цель функции, то функция не сможет вернуть осмысленный результат. Поэтому выбросьте исключение. Это приведет к переходу к ближайшему блоку catch или finally на стеке вызовов. Возврата к функции, которая выбросила исключение, не будет.
Если вы хотите зайти в свой код в отладчике, чтобы отследить вызовы Console.WriteLine(), вам нужно удалить строку throw new NotSupportedException() из своего кода и перекомпилировать его.
Если вас беспокоит, что в методе может возникнуть исключение, но вы хотите, чтобы метод продолжал работать, добавьте обработчик ошибок внутри метода.
class Test
{
public void s()
{
try
{
// Code that may throw an exception
throw new NotSupportedException();
}
catch(Exception ex)
{
// Handle the exception - log?, reset some values?
}
string @class = "" ;
Console.WriteLine(@class);
Console.ReadLine();
}
}
Вы также можете вернуть логическое или другое значение, чтобы указать состояние.
Для этого кода это невозможно. Если вы разобьете задачи на более мелкие фрагменты, вы сможете возобновить выполнение на следующем фрагменте. Но обычно проще иметь другой механизм, чем исключения, для сообщения о нефатальных ошибках, например, функцию обратного вызова, которая возвращает, продолжать или нет.
Программа перестает выполняться, потому что в методе Main() нет следующего кода для выполнения! Вы можете добавить в код следующую строку, чтобы программа продолжала выполняться до тех пор, пока не появится консольный ввод:
Console.ReadLine();
Вы можете использовать функцию "step-over" в отладке для достижения этого на основе каждого запуска.
Отказ от ответственности: я не предлагаю вам делать это на самом деле.
Вы можете имитировать старый стиль VB On Error Resume Next с помощью следующего кода.
public static class ControlFlow
{
public static Exception ResumeOnError(Action action)
{
try
{
action();
return null;
}
catch (Exception caught)
{
return caught;
}
}
}
А затем его можно использовать следующим образом.
public static void Main()
{
ControlFlow.ResumeOnError(() => { throw new NotSupportedException(); });
ControlFlow.ResumeOnError(() => { Console.WriteLine(); });
ControlFlow.ResumeOnError(() => { Console.ReadLine(); });
}
Выполнение все еще продолжается, но после перехвата исключения кода нет. Если вы хотите повторно вызывать s, подумайте о переносе блока try / catch в цикл while.