У коді C # ви можете зловити власний виняток, викинутий із глибини в якусь некеровану бібліотеку? Якщо так, чи потрібно щось робити по-іншому, щоб зловити його, або стандартна спроба ... зловити зрозуміти?
Відповіді:
Ви можете використовувати 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);
}
}
}
Зловити без () буде виявляти винятки, що не відповідають CLS, включаючи рідні винятки.
try
{
}
catch
{
}
Для отримання додаткової інформації див. Таке правило FxCop: http://msdn.microsoft.com/en-gb/bb264489.aspx
Рівень взаємодії між C # і власним кодом перетворить виняток у керовану форму, що дозволить його перехопити ваш код C #. Починаючи з .NET 2.0, catch (Exception)слід виявляти що-небудь, крім непоправної помилки.
Десь за допомогою .NET Reflector я бачив такий код:
try {
...
} catch(Exception e) {
...
} catch {
...
}
Хм, C # не дозволяє створювати виняток, що не походить від класу System.Exception. І, наскільки мені відомо, будь-яке кешування винятків за допомогою маршалера взаємодії обертається класом винятків, який успадковує System.Exception.
Отже, моє питання полягає в тому, чи можна вловити виняток, який не є System.Exception.
Це залежить від типу рідного винятку, про який ви говорите. Якщо ви маєте на увазі виняток SEH, то CLR зробить одне з двох.
Обидва вони будуть спіймані простим блоком "catch (Exception)".
Іншим типом власного винятку, який може перейти границю власного / керованого, є винятки C ++. Я не впевнений, як вони відображаються / обробляються. Я припускаю, що оскільки Windows впроваджує винятки C ++ поверх SEH, вони просто відображаються однаково.
Windows implements C++ exceptions on top of SEH- здається, це справедливо лише для ВК?
Майже, але не зовсім. Ви знайдете виняток з
try
{
...
}
catch (Exception e)
{
...
}
але у вас все одно будуть потенційні проблеми. Згідно з MSDN , для того, щоб забезпечити виклик деструкторів викликів, вам доведеться ловити, як:
try
{
...
}
catch
{
...
}
Це єдиний спосіб забезпечити виклик деструктора винятків (хоча я не впевнений, чому). Але це залишає вам компроміс грубої сили проти можливого витоку пам’яті.
До речі, якщо ви використовуєте підхід (Виняток e), вам слід знати різні типи винятків, з якими ви можете зіткнутися. RuntimeWrappedException - це те, до чого буде відображено будь-який керований тип без винятку (для мов, які можуть створювати рядок), а інші - як OutOfMemoryException та AccessViolationException. COM Interop HRESULTS або винятки, крім E___FAIL, відображатимуться на COMException, і, нарешті, наприкінці ви отримаєте SEHException для E_FAIL або будь-яке інше некартоване виняток.
То що ти повинен робити? Найкращий вибір - не викидати виключення зі свого некерованого коду! Ха-ха. Насправді, якщо у вас є вибір, встановіть бар'єри та невдачі, які роблять вибір, який гірший, шанс витоку пам'яті під час обробки винятків або невідомість, яким типом є ваш виняток.
Якщо ви використовуєте
try
{
}
catch(Exception ex)
{
}
він захопить ВСІ винятки, залежно від того, як ви викликаєте зовнішні бібліотеки, ви можете отримати виняток, пов’язаний із ком, який інкапсулює помилку, але помилку виявить.