Я не вижу, как вы можете прямо установить один обработчик для всех сигналов. Однако вы можете получить справедливо закройте с помощью sigfillset()
, чтобы сгенерировать набор, содержащий все допустимые номера сигналов, а затем перебрать возможные номера сигналов с помощью sigismember()
, чтобы определить, находится ли это число в наборе и, если да, установите обработчик. Хорошо, я не вижу метода определения того, что такое максимально возможный номер сигнала, поэтому вам, возможно, придется угадать подходящее максимальное значение.
throw;
повторно генерирует исходное исключение и сохраняет исходную трассировку стека.
throw ex;
генерирует исходное исключение, но сбрасывает трассировку стека, уничтожая всю информацию трассировки стека до вашего блока catch
.
throw ex;
throw new Exception (ex.Message);
еще хуже. Он создает новый экземпляр Exception
, теряя исходную трассировку стека исключения, а также его тип. (например, IOException
).
Кроме того, некоторые исключения содержат дополнительную информацию (например, ArgumentException.ParamName
).
throw new Exception (ex.Message);
также уничтожит эту информацию.
В некоторых случаях вам может потребоваться заключить все исключения в пользовательский объект исключения, чтобы вы могли предоставить дополнительную информацию о том, что делал код, когда возникло исключение.
Для этого определите новый класс, который наследует Exception
, добавьте все четыре конструктора исключений и, необязательно, дополнительный конструктор, который также принимает InnerException
. в качестве дополнительной информации и сгенерируйте новый класс исключения, передав ex
в качестве параметра InnerException
. Передав исходное InnerException
, вы сохраните все свойства исходного исключения, включая трассировку стека.
throw
повторно генерирует перехваченное исключение, сохраняя трассировку стека, в то время как throw new Exception
теряет некоторые детали перехваченного исключения.
Обычно вы используете throw
отдельно для регистрации исключения, не обрабатывая его полностью на этом этапе.
У BlackWasp есть хорошая статья под названием Выдача исключений в C # .
Ваш второй пример сбросит трассировку стека исключения. Первый пример наиболее точно сохраняет происхождение исключения. Также вы разворачиваете исходный тип, что является ключевым для понимания того, что именно пошло не так... Если второй способ необходим для функциональности - например, для добавления расширенной информации или повторного разворачивания со специальным типом, таким как пользовательский 'HandleableException', то просто убедитесь, что свойство InnerException тоже установлено!
Самое важное отличие состоит в том, что второе выражение стирает тип исключения. И тип исключения играет жизненно важную роль в перехвате исключений:
public void MyMethod ()
{
// both can throw IOException
try { foo(); } catch { throw; }
try { bar(); } catch(E) {throw new Exception(E.message); }
}
(...)
try {
MyMethod ();
} catch (IOException ex) {
Console.WriteLine ("Error with I/O"); // [1]
} catch (Exception ex) {
Console.WriteLine ("Other error"); // [2]
}
Если foo ()
выбрасывает IOException
, [1]
блок catch перехватит исключение. Но когда bar ()
выбрасывает IOException
, оно будет преобразовано в обычное Exception
и не будет поймано блоком захвата [1]
.
Первый сохраняет исходную трассировку стека:
try { ... }
catch
{
// Do something.
throw;
}
Второй позволяет вам изменить тип исключения и / или сообщения и других данных:
try { ... } catch (Exception e)
{
throw new BarException("Something broke!");
}
Существует также третий способ, с помощью которого вы можете передать внутреннее исключение:
try { ... }
catch (FooException e) {
throw new BarException("foo", e);
}
Я бы рекомендовал использовать:
Бросок нового исключения уничтожает текущую трассировку стека.
throw;
сохраняет исходный след стека и почти всегда более полезен. Исключением из этого правила является случай, когда вы хотите обернуть Исключение в собственное Исключение. Тогда вам следует сделать следующее:
catch(Exception e)
{
throw new CustomException(customMessage, e);
}
throw
предназначен для повторного броска пойманного исключения. Это может быть полезно, если вы хотите что-то сделать с исключением, прежде чем передавать его по цепочке вызовов.
Использование throw
без аргументов сохраняет стек вызовов для целей отладки.
При желании вы можете создать новое исключение, при этом исходное исключение будет установлено как внутреннее исключение.