Здесь две вещи, с моей точки зрения.
Не возмутительно ожидать, что само исключение будет содержать информацию о значении i или, точнее, о контексте, в котором оно было оценено, и о том, что пошло не так. Для тривиального примера я бы никогда не бросил стрит InvalidArgumentException
; скорее, я бы удостоверился, что передал точное описание в конструктор, например
<code>
public void doStuff(int arg) {
if (arg < 0) {
throw new InvalidArgumentException("Index must be greater than or equal to zero, but was " + arg);
}
...
Это может не явно записать значение i, но в большинстве случаев вы сможете понять, в чем заключалась проблема с вашим вводом, вызвавшим ошибку. Это также аргумент в пользу цепочки исключений - если вы ловите, переносите и перебрасываете исключения на каждом концептуальном уровне, то каждая упаковка может добавлять свои собственные релевантные переменные, которые слишком высоки, чтобы их можно было увидеть или понять из-за фундаментальной ошибки низкого уровня .
В качестве альтернативы, если вещи действительно слишком абстрагированы для вашей myCall
функции, чтобы знать, что происходит, то я обнаруживаю, что ведение журнала на более высоком уровне многословия перед выполнением вызова работает хорошо, например,
<code>try
{
<...>
for ( int i = 0 ; i < n ; i++ )
DebugLog("Trying myCall with i = " + i);
myCall();
<...>
}
catch ( Exception exception )
{
Log( "Failure ! Maybe in myCall() ? Don't know. i's value ? No clue." );
}
Таким образом, если что-то пойдет не так, вы можете просмотреть свой журнал отладки с высокой степенью детализации и выяснить, что было
i
непосредственно перед вызовом, вызвавшим исключение.