Можете ли вы поймать собственное исключение в коде С#?

В коде С# вы можете поймать собственное исключение, которое было выведено из глубины в некоторая неуправляемая библиотека? Если это так, вам нужно сделать что-то по-другому, чтобы поймать его или сделать стандартную попытку... поймать его?

Ответ 1

Вы можете использовать Win32Exception и использовать его свойство NativeErrorCode для правильной обработки.

// http://support.microsoft.com/kb/186550
const int ERROR_FILE_NOT_FOUND = 2;
const int ERROR_ACCESS_DENIED = 5;
const int ERROR_NO_APP_ASSOCIATED = 1155; 

void OpenFile(string filePath)
{
    Process process = new Process();

    try
    {
        // Calls native application registered for the file type
        // This may throw native exception
        process.StartInfo.FileName = filePath;
        process.StartInfo.Verb = "Open";
        process.StartInfo.CreateNoWindow = true;
        process.Start();
    }
    catch (Win32Exception e)
    {
        if (e.NativeErrorCode == ERROR_FILE_NOT_FOUND || 
            e.NativeErrorCode == ERROR_ACCESS_DENIED ||
            e.NativeErrorCode == ERROR_NO_APP_ASSOCIATED)
        {
            MessageBox.Show(this, e.Message, "Error", 
                    MessageBoxButtons.OK, 
                    MessageBoxIcon.Exclamation);
        }
    }
}

Ответ 2

Catch without() будет захватывать исключения, не совместимые с CLS, включая собственные исключения.

try
{

}
catch
{

}

Для получения дополнительной информации см. следующее правило FxCop http://msdn.microsoft.com/en-gb/bb264489.aspx

Ответ 3

Уровень взаимодействия между С# и собственным кодом преобразует исключение в управляемую форму, позволяя ему быть пойманным вашим кодом С#. Начиная с .NET 2.0, catch (Exception) должен улавливать что-либо, кроме неустранимой ошибки.

Ответ 4

Где-то с использованием .NET Reflector я видел следующий код:

try {
  ...
} catch(Exception e) {
  ...
} catch {
  ...
}

Hmm, С# не позволяет исключать исключение из класса System.Exception. И насколько я знаю какое-либо исключение, cautch от interch marshaller завершается классом исключений, который наследует System.Exception.

Итак, мой вопрос в том, можно ли поймать исключение, которое не является исключением System.Exception.

Ответ 5

Это зависит от того, в каком типе родного исключения вы говорите. Если вы ссылаетесь на исключение SEH, CLR будет делать одну из двух вещей.

  • В случае известного кода ошибки SEH он сопоставляет его с соответствующим исключением .NET(т.е. OutOfMemoryException)
  • В случае несовместимого (E_FAIL) или неизвестного кода он просто выкинет экземпляр SEHException.

Оба из них будут пойманы с помощью простого блока catch (Exception).

Другим типом родного исключения, которое может пересекать собственную/управляемую границу, являются исключения С++. Я не уверен, как они отображаются/обрабатываются. Я предполагаю, что, поскольку Windows реализует исключения С++ поверх SEH, они просто отображаются одинаково.

Ответ 6

Почти, но не совсем. Вы поймаете исключение с помощью

try 
{
  ...
}
catch (Exception e)
{
  ...
}

но у вас все еще будут проблемы. Согласно MSDN, чтобы обеспечить исключение, вызываемые деструкторы вызываются, вам придется поймать, например:

try
{
  ...
}
catch
{
  ...
}

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

Кстати, если вы используете подход (Exception e), вы должны знать разные типы исключений, которые могут возникнуть. RuntimeWrappedException - это то, к чему будет управляться любой управляемый тип без исключения (для языков, которые могут вызывать строку), а другие будут отображаться, например OutOfMemoryException и AccessViolationException. COM Interop HRESULTS или исключения, отличные от E___FAIL, будут отображаться в COMException, и, наконец, в конце вы получите SEHException для E_FAIL или любое другое неотображенное исключение.

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

Ответ 7

Если вы используете

try
{

}
catch(Exception ex)
{

}

он будет перехватывать ВСЕ исключения, в зависимости от того, как вы вызываете внешние библиотеки, вы можете получить исключение, связанное с комком, которое инкапсулирует ошибку, но оно поймает ошибку.

Ответ 8

Стандартный try catch должен делать трюк, которому я верю.

У меня возникает аналогичная проблема с исключением System.data, бросающим исключение sqlClient, которое было неотобрано, добавив try..catch в мой код, сделал трюк в экземпляре