Как отбросить предыдущее исключение из вложенного блока try-catch?(С #) - PullRequest
12 голосов
/ 25 октября 2011

У меня есть код, который пытается преобразовать тип. Если это не удается, я хочу попробовать что-то еще, и если это также не удается, а затем сбросить исходное исключение, предпринятое при первом преобразовании. Проблема в том, что единственный способ повторного броска, который я знаю, состоит в том, чтобы 'throw;' сидел в конце блока захвата. Что происходит, когда я хочу, чтобы повторный бросок происходил только из другого блока catch?

try 
{
    valueFromData = Convert.ChangeType(valueFromData, pi.PropertyType);
} 
catch(InvalidCastException e)
{
    Debug.WriteLine(String.Concat("Info - Direct conversion failed. Attempting to convert using String as an intermidiate type."));
    try { valueFromData = Convert.ChangeType(valueFromData.ToString(), pi.PropertyType); }
    catch { throw e; }
}

Как вы можете видеть выше, я должен использовать 'throw e;', который сбрасывает стек вызовов.

Единственный обходной путь, который у меня пока есть, (imo) брутто:

bool handled = true;
... 
catch { handled = false; }
if( !handled ) throw;

Ответы [ 3 ]

7 голосов
/ 25 октября 2011

Нет способа перебросить исключение из внешнего блока catch внутри блока захвата inner. Лучший способ добиться этого паттерна - заметить, была ли внутренняя операция выполнена успешно

catch (InvalidCastException e) {
  bool threw = false;
  try {
    ...
  } catch { 
    threw = true;
  }
  if (threw) {
    throw;
  }
}
1 голос
/ 25 октября 2011

Я попробовал следующее, и, похоже, для достижения вашей цели, когда возникает 2-е исключение (в данном случае ArgumentException ), оно выдает первое исключение ( InvalidCastException )

[TestMethod]
[ExpectedException(typeof(InvalidCastException))]
public void ReThrowException() {
    var ret = false;

    try {
        ret = F1(1);
    }
    catch (InvalidCastException ex) {

        try {
            ret = F1(2);
        }
        catch (Exception e) {
            Debug.WriteLine(e.Message);
            throw ex;
        }

    }
}


private bool F1(int i) {
    if (i == 1) {
       throw new InvalidCastException();
    } else {
       throw new ArgumentException();
    }
    return false;
}

Надеюсь, это поможет,

Алан.

1 голос
/ 25 октября 2011

Если вы намереваетесь сделать несколько попыток конвертации, тогда, безусловно, имеет смысл использовать не-бросающие операции, где это применимо, чтобы вы полностью обошли проблему.

Предположим, что это невозможно ради аргумента, следующим шагом является вопрос о подходе throw e;. В приведенном вами примере кода, IMHO, вообще нет проблем, если ваш throw сбрасывает стек вызовов. Как только кто-то получит исходный код для этого метода (на который все еще будет указывать модифицированный стек вызовов), я думаю, что это довольно очевидно. Поэтому, хотя сброс стека вызовов всегда является сомнительным решением, в данном конкретном случае должно быть разрешено, потому что не будет существенного недостатка.

Наконец, упомянутый вами обходной путь интересен, а также груб (согласен!).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...