2011-02-06 33 views
20

Có cách nào tốt hơn để bỏ qua một ngoại lệ trong C# hơn là đặt nó lên trong khối try try và không làm gì trong bắt? Tôi thấy cú pháp này rất cồng kềnh. Đối với một codeblock, tôi không thể chỉ đơn giản là "tag" nó theo cách như vậy để thời gian chạy biết được những ngoại lệ để bỏ bê?Bỏ qua Ngoại lệ trong C#

+1

Tôi biết bỏ qua trường hợp ngoại lệ là một thực hành lập trình xấu, nhưng câu hỏi của tôi không phải là. Tôi không thấy một điểm trong việc có một khối bắt rỗng, do đó câu hỏi. –

Trả lời

23

Tôi không nghĩ rằng có một trick để tránh ngoại lệ nhưng bạn có thể sử dụng đoạn mã sau:

public void IgnoreExceptions(Action act) 
{ 
    try 
    { 
     act.Invoke(); 
    } 
    catch { } 
} 

Sử dụng phương pháp này trông giống như:

IgnoreExceptions(() => foo()); 

Một giải pháp khác là sử dụng AOP (Aspect Oriented Programming) - có một công cụ gọi là PostSharp cho phép bạn tạo một thuộc tính có thể bắt tất cả các ngoại lệ trong assembly/class/method cụ thể, gần hơn với những gì bạn đang tìm kiếm.

+8

* @ Dror *, ý tưởng hay. Tuy nhiên, lưu ý rằng mã của bạn có chứa một lỗi nhỏ: CLR thực sự cho phép * bất kỳ giá trị * nào được ném ra, không chỉ các đối tượng kiểu 'Ngoại lệ' (hạn chế này chỉ được thực thi bởi C#). Vì vậy, bạn nên viết lại khối 'catch' của bạn đơn giản như sau: **' catch {} '**; nếu không, một số trường hợp ngoại lệ bất thường nhất định có thể thực sự lấy lại cho người gọi! - Xem ví dụ [bài viết blog này] (http://blogs.msdn.com/b/shawnfa/archive/0001/01/01/400749.aspx) (khoảng hai trang xuống) để tham khảo. – stakx

+0

(Tôi đã sửa chữa nó ngay bây giờ. Tôi đã nhân dịp khi tôi phát hiện một lỗi đánh máy trong mã của bạn, mà tôi đã sửa chữa cũng. Tôi hy vọng bạn không nhớ.) – stakx

+1

Thay vì act.Invoke(), tại sao không sử dụng hành động()? –

1

Không. Khi ngoại lệ xảy ra, chúng sẽ sao lưu ngăn xếp cuộc gọi cho đến khi chúng được xử lý bởi khối catch hoặc toàn bộ quá trình chấm dứt.

5

Bạn có thể làm điều đó với AOP. Postsharp ví dụ sẽ cho phép bạn dễ dàng thực hiện một thuộc tính như vậy sẽ bỏ qua các ngoại lệ cụ thể trong các phương thức mà bạn đã áp dụng một thuộc tính như vậy. Nếu không có AOP tôi không thấy bất kỳ cách nào tốt để làm điều đó (nếu chúng ta giả định rằng có một cách tốt để làm những việc như vậy;)).

Với PostSharp bạn sẽ có thể để trang trí các phương pháp của bạn theo cách này:

[IgnoreExceptions(typeof(NullReferenceException), typeof(StackOverflowException))] 
void MyMethod() { ... } 
3

Một cách là để tận advantge của Aspect Oriented Programming (AOP). Hãy xem PostSharp. Here là một ví dụ về việc sử dụng một thuộc tính ngoại lệ trên một phương thức để nếu một ngoại lệ xảy ra, bạn có thể xử lý nó với một khối try..catch.

CHỈNH SỬA:

Có, đề xuất của Dror cũng là một gợi ý tốt. Tôi đã xem các ví dụ về điều đó trong Thư viện doanh nghiệp. Điều đó sẽ tốt hơn nếu bạn không muốn có một khung bên thứ ba trong dự án của mình (ví dụ: PostSharp).

2

Tôi không biết bất kỳ cơ chế nào cho phép bạn thực hiện việc này.

Nói chung, nó cũng được coi là một hành vi rất xấu để bỏ qua ngoại lệ. Các trường hợp ngoại lệ (hoặc phải luôn luôn) được nêu ra vì một lý do chính đáng; nếu không có gì khác, bạn nên đăng nhập ít nhất.

Nếu bạn biết rằng một loại ngoại lệ nhất định không quan trọng đối với ứng dụng của mình, bạn có thể ngăn không cho nó bị lỗi khi sử dụng sự kiện Application.UnhandledException, kiểm tra loại ngoại lệ đó. Lưu ý rằng điều này sẽ vẫn truyền bá ngoại lệ thông qua tất cả các khung ngăn xếp ở phía dưới cùng.

0

Không. Nếu ngoại lệ được ném, nó thường là lỗi nghiêm trọng đã xảy ra. Bạn không muốn bỏ qua nó.

Thay vào đó bạn nên viết lại mã của mình để kiểm tra lỗi và chỉ khi nó thực sự không thành công, ngoại lệ sẽ được truyền.

Ví dụ sử dụng Int32.TryParse thay vì Int32.Parse để kiểm tra xem đối tượng có phải là số nguyên hợp lệ hay không. Hãy nhớ rằng các ngoại lệ rất tốn kém khi chúng được đúc và nhiều phôi ảnh hưởng nghiêm trọng đến hiệu suất của ứng dụng của bạn.

+2

Jon skeet trích dẫn: "Nếu bạn đã từng đến mức mà các ngoại lệ ảnh hưởng đáng kể đến hiệu suất của bạn, bạn có vấn đề về việc sử dụng ngoại lệ của bạn ngoài hiệu suất." http://www.yoda.arachsys.com/csharp/exceptions2.html –

0

Các khối catch rỗng là một mùi mã rất hôi.Tóm lại, bạn không nên theo đuổi cách viết tắt của chúng.

Quy tắc số 1 là "không bắt được nếu bạn không thể xử lý". Quy tắC# 1a là "nếu bạn không thực sự xử lý Ngoại lệ, hãy ném lại."

Nếu bạn chỉ đang cố ngăn ứng dụng bị rơi, có nhiều cơ chế thích hợp hơn để sử dụng trong hầu hết các trường hợp. .NET bao gồm các sự kiện UnhandledException ở cấp Application, Dispatcher và AppDomain, cũng như các sự kiện dành riêng để thông báo cho bạn về các ngoại lệ chưa được xử lý trên các chủ đề nền. Ở cấp độ này, nếu bạn không thể xác minh trạng thái của ứng dụng, tùy chọn tốt nhất của bạn có thể là thông báo cho người dùng về điều gì đó đã xảy ra và chấm dứt ứng dụng.

+0

Ăn một ngoại lệ là xử lý ngoại lệ. Ví dụ: bạn sẽ không muốn khung đăng nhập của mình ném các ngoại lệ ngăn chức năng nghiệp vụ của bạn hoạt động. Về cơ bản, bạn không muốn công việc chính của bạn thất bại chỉ vì có thể có một vấn đề trong mã không cần thiết tùy chọn. Quy tắC# 1 Nên thực sự không thực hiện bất kỳ quy tắc nào, bởi vì tất cả đều phụ thuộc. Bạn luôn luôn cần phải hiểu tại sao bạn làm điều gì đó, và những gì nó có liên quan. Ngoài ra, câu trả lời của bạn mang lại sự rõ ràng cho câu hỏi ban đầu theo cách nào? – NoOneSpecial

0

Tôi muốn đóng góp các phương pháp mở rộng mà tôi đã tạo dựa trên câu trả lời trước đó. Hy vọng nó sẽ giúp ai đó.

/// <summary> 
/// Extension methods for <see cref="Action"/> objects. 
/// </summary> 
public static class ActionExtensions 
{ 
    /// <summary> 
    /// Executes the <paramref name="action"/> and ignores any exceptions. 
    /// </summary> 
    /// <remarks> 
    /// This should be used in very rare cases. 
    /// </remarks> 
    /// <param name="action">The action to execute.</param> 
    public static void IgnoreExceptions(this Action action) 
    { 
     try { action(); } 
     catch { } 
    } 

    /// <summary> 
    /// Extends an existing <see cref="Action"/> so that it will ignore exceptions when executed. 
    /// </summary> 
    /// <param name="action">The action to extend.</param> 
    /// <returns>A new Action that will ignore exceptions when executed.</returns> 
    public static Action AddIgnoreExceptions(this Action action) 
    { 
     return() => action.IgnoreExceptions(); 
    } 
} 

Và các đơn vị kiểm tra:

[TestClass] 
public class ActionExtensionsTests 
{ 
    [TestMethod] 
    public void IgnoreException() 
    { 
     Action justThrow =() => { throw new InvalidOperationException(); }; 
     justThrow.IgnoreExceptions(); 
    } 
    [TestMethod] 
    public void AddIgnoreException() 
    { 
     Action justThrow =() => { throw new InvalidOperationException(); }; 
     var newAction = justThrow.AddIgnoreExceptions(); 
     newAction(); 
    } 
} 
0
public static void Ignore<T>(Action a) where T : Exception 
    { 
     try 
     { 
      a(); 
     } 
     catch (T) 
     { 
     } 
    } 

Cách sử dụng:

Ignore<InvalidOperationException>(() => foo()); 
Các vấn đề liên quan