Trong mã C #, bạn có thể bắt được một ngoại lệ gốc được đưa ra từ sâu trong một thư viện không được quản lý nào đó không? Nếu vậy, bạn có cần phải làm bất cứ điều gì khác để nắm bắt nó hoặc một tiêu chuẩn thử ... bắt lấy nó?
Câu trả lời:
Bạn có thể sử dụng Win32Exception và sử dụng thuộc tính NativeErrorCode của nó để xử lý nó một cách thích hợp.
// 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);
}
}
}
Catch without () sẽ bắt các ngoại lệ không tuân thủ CLS bao gồm các ngoại lệ gốc.
try
{
}
catch
{
}
Xem quy tắc FxCop sau để biết thêm thông tin http://msdn.microsoft.com/en-gb/bb264489.aspx
Lớp tương tác giữa C # và mã gốc sẽ chuyển đổi ngoại lệ thành một biểu mẫu được quản lý, cho phép mã C # của bạn bắt được ngoại lệ. Kể từ .NET 2.0, catch (Exception)
sẽ gặp bất kỳ lỗi nào khác ngoài lỗi không thể khôi phục.
Ở đâu đó bằng cách sử dụng .NET Reflector, tôi đã thấy đoạn mã sau:
try {
...
} catch(Exception e) {
...
} catch {
...
}
Hmm, C # không cho phép ném một ngoại lệ không bắt nguồn từ lớp System.Exception. Và theo như tôi đã biết, bất kỳ cautch ngoại lệ nào bởi bộ điều phối tương thích đều được bao bọc bởi lớp ngoại lệ kế thừa System.Exception.
Vì vậy, câu hỏi của tôi là liệu có thể bắt được một ngoại lệ không phải là System.Exception hay không.
Điều này phụ thuộc vào loại ngoại lệ bản địa mà bạn đang nói đến. Nếu bạn đang đề cập đến một ngoại lệ SEH thì CLR sẽ thực hiện một trong hai điều.
Cả hai điều này sẽ được bắt bằng một khối "catch (Exception)" đơn giản.
Loại ngoại lệ gốc khác có thể vượt qua ranh giới riêng / được quản lý là ngoại lệ C ++. Tôi không chắc chúng được ánh xạ / xử lý như thế nào. Tôi đoán là vì Windows triển khai các ngoại lệ C ++ trên SEH, chúng chỉ được ánh xạ theo cùng một cách.
Windows implements C++ exceptions on top of SEH
- điều này dường như chỉ đúng với VC?
Hầu như, nhưng không hoàn toàn. Bạn sẽ bắt được ngoại lệ với
try
{
...
}
catch (Exception e)
{
...
}
nhưng bạn vẫn sẽ có những vấn đề tiềm ẩn. Theo MSDN , để đảm bảo các trình hủy ngoại lệ được gọi, bạn sẽ phải bắt như:
try
{
...
}
catch
{
...
}
Đây là cách duy nhất để đảm bảo một trình hủy ngoại lệ được gọi (mặc dù tôi không chắc tại sao). Nhưng điều đó khiến bạn phải đánh đổi tính vũ phu với khả năng bị rò rỉ bộ nhớ.
Ngẫu nhiên, nếu bạn sử dụng cách tiếp cận (Exception e), bạn sẽ biết các loại ngoại lệ khác nhau mà bạn có thể gặp phải. RuntimeWrappedException là thứ mà bất kỳ kiểu không ngoại lệ nào được quản lý sẽ được ánh xạ tới (đối với các ngôn ngữ có thể ném một chuỗi) và những ngôn ngữ khác sẽ được ánh xạ, chẳng hạn như OutOfMemoryException và AccessViolationException. COM Interop HRESULTS hoặc các ngoại lệ không phải E___FAIL sẽ ánh xạ tới COMException, và cuối cùng khi kết thúc, bạn có SEHException cho E_FAIL hoặc bất kỳ ngoại lệ chưa được ánh xạ nào khác.
Vậy bạn nên làm gì? Lựa chọn tốt nhất là đừng ném các ngoại lệ khỏi mã chưa được quản lý của bạn! Hả. Thực sự, mặc dù nếu bạn có quyền lựa chọn, hãy đặt ra các rào cản và thất bại khiến lựa chọn nào trở nên tồi tệ hơn, khả năng bị rò rỉ bộ nhớ trong quá trình xử lý ngoại lệ hoặc không biết loại ngoại lệ của bạn là gì.
Một tiêu chuẩn thử bắt sẽ thực hiện thủ thuật mà tôi tin tưởng.
Tôi gặp phải sự cố tương tự với một ngoại lệ System.data ném một ngoại lệ sqlClient mà không có ý nghĩa, thêm một try..catch vào mã của tôi đã thực hiện thủ thuật trong trường hợp này
Nếu bạn sử dụng một
try
{
}
catch(Exception ex)
{
}
nó sẽ bắt TẤT CẢ các ngoại lệ, tùy thuộc vào cách bạn gọi các thư viện bên ngoài, bạn có thể nhận được một ngoại lệ liên quan đến com đóng gói lỗi nhưng nó sẽ bắt lỗi.