2011-02-06 55 views
20

有沒有更好的方法來忽略C#中的異常,而不是將它放在try catch塊中,並在catch中無作爲?我覺得這個語法很麻煩。對於代碼塊,我不能簡單地以這種方式「標記」它,以便運行時知道要忽略哪些異常?在C中忽略異常#

+1

我知道忽略異常是一個不好的編程習慣,但我的問題是不是。我沒有看到有一個空的catch塊,因此這個問題。 – 2011-02-07 15:07:28

回答

23

我不認爲有一個小竅門,以避免異常,但你可以用下面的代碼片段:

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

使用方法是這樣的:

IgnoreExceptions(() => foo()); 

另一種解決方案是使用AOP(面向方面​​的編程) - 有一個名爲PostSharp的工具,它使您能夠創建一個屬性,可以捕獲特定程序集/類/方法中的所有異常,這更接近您要查找的內容。

+8

* @ Dror *,好主意。但是,請注意,您的代碼包含一個微妙的錯誤:CLR實際上允許拋出任何*值,而不僅僅是Exception類型的對象(此限制僅由C#強制執行)。所以,你應該簡單地重寫你的`catch`塊:**`catch {}`**;否則,某些異常的異常實際上可能會返回給調用者! - 見例如[本博客文章](http://blogs.msdn.com/b/shawnfa/archive/0001/01/01/400749.aspx)(約兩頁下)供參考。 – stakx 2011-02-06 12:16:56

+0

(我現在已經修復了,當我發現你的代碼中有另一個錯誤的時候,我也糾正了錯誤,我希望你不要介意) – stakx 2011-02-06 12:27:21

+1

而不是act.Invoke(),爲什麼不使用法案()? – 2015-06-22 18:57:39

1

否。當出現exceptios時,它們會返回調用堆棧,直到它們由catch塊處理或者整個過程終止。

5

您可以使用AOP來完成。例如Postharp將允許您輕鬆實現這樣一個屬性,該屬性將跳過應用此類屬性的方法中的特定異常。如果沒有AOP,我認爲沒有什麼好的方法可以做到這一點(如果我們假設有一種很好的方法來做這樣的事情))。

隨着Postsharp你將能夠裝點這樣的方法:

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

一種方法是採取面向方面編程(AOP)的advantge。看看PostSharpHere是在方法上使用異常屬性的示例,因此如果發生異常,則可以在try..catch塊處理它。

編輯:

是啊,德羅爾的建議也是一個很好的一個。我在企業庫中看到過這方面的例子。如果你不想在你的項目中使用第三方框架(比如PostSharp),那會更好。

2

我不知道任何機制,可以讓你這樣做。

通常,忽略異常也被認爲是一種非常糟糕的做法。例外情況是(或應該總是)有充分的理由提出;如果沒有別的,你至少應該記錄它們。

如果您知道某種類型的異常對您的應用程序不是至關重要的,可以使用Application.UnhandledException事件來防止它崩潰,檢查是否有這種異常。請注意,這仍將通過所有堆棧幀將異常傳播到最底層。

0

不。如果拋出異常,通常會發生嚴重錯誤。你不想忽視它。

相反,您應該重寫您的代碼來檢查錯誤,並且只有在確實失敗時纔會拋出異常。

例如使用Int32.TryParse而不是Int32.Parse來檢查對象是否爲有效整數。請記住,異常在投射時非常昂貴,而且許多投射會嚴重影響應用程序的性能。

0

空的catch塊是非常臭的代碼氣味。總之,你不應該追求寫他們的速記方式。

規則1是,「如果你不能處理它,不要抓住它。」 規則#1a是「如果你實際上沒有處理異常,請重新拋出異常。」

如果您只是試圖阻止應用程序崩潰,那麼在大多數情況下可以使用更合適的機制。 .NET包括Application,Dispatcher和AppDomain級別的UnhandledException事件,以及專門用於通知您後臺線程上未處理的異常的事件。在這個級別上,如果你無法驗證你的應用程序的狀態,最好的選擇可能是通知用戶發生了不好的事情並終止應用程序。

0

我想根據以前的答案提供我創建的擴展方法。希望它能幫助別人。

/// <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(); 
    } 
} 

而且單元測試:

[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) 
     { 
     } 
    } 

要使用:

Ignore<InvalidOperationException>(() => foo());