簡體   English   中英

Resharper異常重新拋出可能是有意的

[英]Resharper Exception rethrow possibly intended

考慮一下這種方法(原諒Chuck Norris幽默的悲慘嘗試:)):

public class ChuckNorrisException : Exception
{
    public ChuckNorrisException()
    {
    }

    public ChuckNorrisException(string message)
        : base(message)
    {
    }

    public ChuckNorrisException(string message, Exception cause)
        : base(message, cause)
    {
    }

    protected ChuckNorrisException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }
}

static void ExceptionTest(double x)
{
    try
    {
        double y = 10 / x;
        Console.WriteLine("quotient = " + y);
    }
    catch (Exception e)
    {
        e = e is DivideByZeroException ? new ChuckNorrisException("Only Chuck Norris can divide by 0!", e) :
            e;
        throw e;
    }
}

在resharper中,我收到一條警告“throw e”行說“異常重新拋出可能意圖”。 但顯然在這種情況下,這不是意圖,因為e可以包裝在ChuckNorrisException中,如果我只是使用“throw”,那么包裝的異常就不會被拋出。

我知道我可以抑制resharper警告,但是如果我沒有弄錯的話,它會在所有情況下關閉。 我只是想知道是否還有其他人遇到過此事。 我發現的唯一解決方法是創建另一個異常變量(例如e2),然后拋出它。 這可能是我能在這里做的最好的。 似乎resharper可以檢測到這個問題並且足夠聰明,知道如果e被修改,那么拋出e就可以了。

謝謝。

[編輯]對不起,我忘記了一步。 在拋出之前,我需要記錄異常,所以我不能這樣做:

e = e is DivideByZeroException ? new ChuckNorrisException("Only Chuck Norris can divide by 0!", e) :
            e;
throw e;

我要做:

e = e is DivideByZeroException ? new ChuckNorrisException("Only Chuck Norris can divide by 0!", e) :
            e;
LogException(e);
throw e;

也許我不理解這個問題,所以如果我有錯誤的結論,請糾正我。

這里有兩種情況:

  1. 首先是你抓住原來的例外。 然后將其作為內部異常包裝在新的異常實例中,然后拋出新的異常。 在這種情況下不會丟失任何信息(內部異常保留所有信息),因此不會給出警告。

  2. 第二個是你抓住並重新拋出原始異常。 如果你重新拋出,你永遠不應該使用“throw e”,因為它會篡改堆棧跟蹤。 這就是ReSharper打印警告的原因。 要重新拋出捕獲的異常,您應該自己使用“throw”關鍵字。

這個問題的答案解釋得比我好。 由於微妙的副作用以及使這個細節錯誤的人數眾多,我個人認為重新拋出的語法是有缺陷的。

無論如何,這是對你收到警告的原因的描述。 以下是我要做的事情:

catch(DivideByZeroException e)
{
    // we don't catch any other exceptions because we weren't
    // logging them or doing anything with the exception before re-throwing
    throw new ChuckNorrisException("Useful information", e);
}

*編輯 - 如果您需要記錄異常,您可以執行此類操作。 注意:這是我首選的解決方案,因為我認為它讀起來更好,並且不像自己查詢異常類型那樣包含錯誤:

// catch most specific exception type first
catch(DivideByZeroException e)
{
    Log(e); 
    throw new ChuckNorrisException("Useful information", e);
} 
catch(Exception e) // log & re-throw all other exceptions
{
    Log(e);
    throw; // notice this is *not* "throw e"; this preserves the stack trace
}

另一種選擇是:

catch(Exception e)
{
    Log(e);
    if(e is DivideByZeroException)
    {
        // wrap + throw the exception with our new exception type
        throw new ChuckNorrisException("useful info", e);
    }

    // re-throw the original, preserving the stack trace
    throw;
}

這將與您發布的代碼具有相同的效果,不應導致警告。

catch (DivideByZeroException de)
    {
        throw new ChuckNorrisException("Only Chuck Norris can divide by 0!", de);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM