[英]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;
也許我不理解這個問題,所以如果我有錯誤的結論,請糾正我。
這里有兩種情況:
首先是你抓住原來的例外。 然后將其作為內部異常包裝在新的異常實例中,然后拋出新的異常。 在這種情況下不會丟失任何信息(內部異常保留所有信息),因此不會給出警告。
第二個是你抓住並重新拋出原始異常。 如果你重新拋出,你永遠不應該使用“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.