[英]C# - Rethrow an exception without setting it to an variable
大家可能都知道,以這種方式在 c# 中捕獲並重新拋出異常是邪惡的,因為它會破壞堆棧跟蹤:
try
{
if(dummy)
throw new DummyException();
}
catch (DummyException ex)
{
throw ex;
}
在不丟失堆棧跟蹤的情況下重新引發異常的正確方法是:
try
{
if(dummy)
throw new DummyException();
}
catch (DummyException ex)
{
throw;
}
唯一的問題是我收到很多編譯警告:“變量'ex'已聲明但從未使用過”。 如果你有很多這些,有用的警告可能隱藏在垃圾中。 所以,這就是我所做的:
try
{
if(dummy)
throw new DummyException();
}
catch (DummyException)
{
throw;
}
catch(AnotherException ex)
{
//handle it
}
這似乎可行,但我想知道重新拋出未設置為變量的異常是否有任何不利之處。 .net 如何威脅這個?
提前致謝
編輯:我已經稍微改變了我的代碼,以更清楚我想要做什么,因為有些人誤解了
沒有缺點。 您只是告訴編譯器“我計划捕獲此異常,但我不需要對實際異常的引用”,它不會影響事物的拋出方式或異常的工作方式。 您的后一個示例是做您想做的事的理想方式,但是如果您只是要立即throw;
街區里什么都沒有,那為什么要抓到呢?
我想知道重新拋出未設置為變量的異常是否有任何不利之處。
不,根本沒有缺點。 僅當您想在代碼中引用異常時才需要變量,但由於您不需要使用throw
語句來執行此操作,因此您根本不需要變量。
並且您在嘗試消除“嘈雜”的編譯器警告方面擁有完全正確的想法。 他們傾向於隱藏您確實想要修復的重要錯誤,並且獲得干凈的構建總是很重要的。 最好的解決方案是簡單地重寫代碼以使用無參數的catch
子句。
但是,請注意,在我看到的 82% 的情況下* ,編寫使用throw
的代碼是錯誤的。 您通常不應該捕獲您不知道如何處理的異常,並且您唯一打算的“處理”策略是重新拋出它們。 在某些情況下,即使使用throw
也會重置調用堆棧,從而導致您丟失重要的調試信息。 還有更好的替代方法來記錄捕獲/重新拋出的異常。 您可以在這些問題的答案中找到更多信息:
讓異常冒出來並在一個中心位置處理它們絕對沒有錯。 要記住的規則是您不應該使用異常來進行流控制。 但是在低級代碼中拋出異常並在 UI 代碼中向用戶顯示更高堆棧的錯誤消息並沒有錯。 閱讀 Microsoft處理異常的最佳實踐以獲取一些一般提示。
*略高於 當場統計的百分比。
如果你沒有在catch
塊中對DummyException
做任何事情(你不能這樣做,因為你沒有給它一個標識符),為什么不完全擺脫try/catch
塊呢? 例如,只需這樣做:
throw new DummyException();
盡管到那時,我可能會評估您在這里嘗試完成的工作並重新考慮您的應用程序架構,以免以這種方式依賴異常傳播。
如果您只是要重新投擲,為什么要抓住? 無論如何,您可能想看看這個先前的討論。 雖然不完全相同,但討論的大部分內容都是相關的:
實際上使用“throw”拋出異常; 是一個.Net最佳實踐,因為它保留了異常堆棧跟蹤。
使用“throw ex;”拋出異常被認為是最糟糕的做法,因為它會丟失原始堆棧跟蹤,應該避免。
為什么要這樣抓又扔? 為什么人們總是不得不假設他們知道每個案例? 答:數據庫事務。
如果您有更好的方法來做到這一點,請說出 Proton 博士,沒有冒犯。 請記住,有很多不同的數據庫系統在使用,但大多數都支持事務控制(開始/提交/回滾)並具有 C# 接口。
偽代碼(簡化案例):
try
{
db.beginTrans();
db.doStuff();
db.doOtherStuff();
db.commitTrans();
}
catch
{
db.rollbackTrans();
throw;
}
現在,丟失 doStuff() 或 doOtherStuff() 是否失敗的細節非常煩人,我看不出 C# 在這種情況下會丟棄行號信息的任何充分理由。 但它似乎。 因此,谷歌搜索和我隨后的到來。 如果我遺漏了什么,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.