另一個人asked a similar question但答案並不清楚。代碼合同可以取代參數驗證嗎?
我們的項目中有很多參數驗證代碼。他們大多是零參數檢查公共方法只:
if (param == null)
{
throw new ArgumentNullException("param");
}
這些檢查不是規範的一部分。它們的主要用途是在編程錯誤的情況下獲得更安全的堆棧轉儲。如果這樣一個簡單的檢查沒有完成,你可以在一個其他圖書館中間的一個隨機點中以NullReferenceException
結束十個深度。這使整個回溯到根本原因過程更長。驗證檢查在語義上是清晰的,可以讓您更早地發現問題。
既然我們這麼做了,我們一直在尋找更短的方法來做這樣的檢查。如:
ArgumentHelper.ThrowIfNull(param, "param");
或類似的語法。我們希望避免基本上的開銷。 if-throw
語法使得代碼不必要的很長。
當我試驗這樣的語法時,我注意到我收斂到類似於斷言和代碼合同的語法。代碼合同非常有吸引力,因爲在開發週期的早期就有可能進行靜態分析和捕獲錯誤。
然而,據我所知代碼合同並沒有設計來補救「輸入驗證」問題或任何類型的驗證問題。 Because the exceptions raised by it are not meant to be caught。他們不是爲了使調試更容易,因爲默認行爲是剝離發佈版本中的這些檢查的代碼。 The rewriter just seems like a hack around it and it's not very performant either。
我從所有的理解是「靜態驗證」和「參數驗證」有不同的目標,因此它們不能互換。然而,使用Code.Contracts
作爲我的開場白if-then-throw
聽起來很自然,我開始不知道自己是否有錯。
我的問題是:使用代碼合同進行參數驗證有效嗎?是否有一個明確的問題,我可以問任何驗證代碼,並提出一個答案,如:「是的,你可以使用代碼合同來檢查這個」和「不,你不能使用代碼合同來檢查」?我如何做出區分?
我想出了「如果我刪除了合同聲明,該功能是否能正常工作?」。這是一個正確的方法嗎?
還檢查了其拋出異常,並提供代碼契約在一個非常乾淨的方式我的擴展方法:http://blog.rsuter.com/elegant-method-parameter-validation- with-code-contracts-support/ –
@RicoSuter您的評論仍需要啓用代碼合同的運行時檢查。看到我的答案爲什麼這是不好的:http://stackoverflow.com/a/25700857/54937 –
不,你有合同和通常的拋出異常,即使運行時驗證被禁用,拋出異常... –