Это то, что можно считать ожидаемым.Изменение трассировки стека является обычным случаем, если вы укажете throw ex;
, FxCop уведомит вас об изменении стека.Если вы сделаете throw;
, предупреждение не будет сгенерировано, но трасса будет изменена.Так что, к сожалению, пока лучше не ловить бывшего или бросать его как внутреннего.Я думаю, что это следует рассматривать как влияние Windows или что-то подобное - отредактировано . Джефф Рихтер описывает эту ситуацию более подробно в своем "CLR via C #" :
Следующий код генерирует тот же объект исключения, который он перехватил, и вызываетCLR для сброса своей начальной точки для исключения:
private void SomeMethod() {
try { ... }
catch (Exception e) {
...
throw e; // CLR thinks this is where exception originated.
// FxCop reports this as an error
}
}
Напротив, если вы перебрасываете объект исключения, используя само ключевое слово throw, CLR не сбрасывает начальную точку стека.Следующий код повторно генерирует тот же объект исключения, который он перехватил, в результате чего CLR не сбрасывает исходную точку для исключения:
private void SomeMethod() {
try { ... }
catch (Exception e) {
...
throw; // This has no effect on where the CLR thinks the exception
// originated. FxCop does NOT report this as an error
}
}
Фактически, единственное различие между этими двумя фрагментами кода состоит в том, чтоCLR считает исходное место, где было сгенерировано исключение. К сожалению, когда вы выбрасываете или перебрасываете исключение, Windows сбрасывает начальную точку стека. Таким образом, если исключение становится необработанным, местоположение стека, которое сообщается в службу отчетов об ошибках Windows, является местоположением последнего выброса или повторного запроса-throw, даже если CLR знает расположение стека, в которое было сгенерировано исходное исключение.Это прискорбно, потому что это затрудняет отладку приложений, которые потерпели неудачу в полевых условиях.Некоторые разработчики сочли это настолько невыносимым, что выбрали другой способ реализации своего кода, чтобы гарантировать, что трассировка стека действительно отражает местоположение, в которое изначально было выдано исключение:
private void SomeMethod() {
Boolean trySucceeds = false;
try {
...
trySucceeds = true;
}
finally {
if (!trySucceeds) { /* catch code goes in here */ }
}
}