[英]The best way to assert pre-condition and post-condition of arguments and values in .NET?
[英].net assert display condition failed with
好的,我已經習慣了舊的C斷言,當它們失敗時,它們會輸出失敗的條件及其所在的行。 (配有預處理器)。
現在,我正在使用F#(。net語言)進行編程,獲得了充滿斷言的代碼。 (嘗試防御性編程)。 我的資產在調用堆棧中顯示一個彈出窗口。 根據文檔 ,還可以傳遞斷言字符串以在失敗時顯示。 所以我可以讓它傳遞我條件的字符串副本。 例如:
assert (x=true, "x=true")
但這違反了重復(避免)主體。
如果我以后決定更改我要聲明的內容。 (也許我意識到當我應該斷言某件事為真時我斷言是假的)然后我必須在兩個地方更改代碼,否則該消息將與我實際檢查的內容不匹配。 如果我忘記了,事情可能真的很混亂。
通常如何處理?
呼應Tomas所說的,您可以使用引號來避免重復。 但是,可以使用我的庫Unquote來生成F#源代碼字符串,而不是使用ToLinqExpression -> ToString
來生成C#源代碼。 將其與適合於生產代碼的實現結合起來(即,使用僅發出no-op ()
的非DEBUG
編譯符號分支來內聯定義Assert
,這意味着在啟用優化的非DEBUG
構建中將完全刪除對Assert
使用):
let inline Assert (q:Expr<bool>) =
#if DEBUG
System.Diagnostics.Debug.Assert(q.Eval(), q.Decompile())
#else
()
#endif
那么斷言表達式Assert <@ (22 + 2) / 2 = ("assert" |> String.length) @>
默認情況下會產生以下彈出對話框(我認為您可以配置System.Diagnostics.Debug
行為):
相比之下, q.ToLinqExpression().ToString()
產生(((22 + 2) / 2) == op_PipeRight("assert", ToFSharpFunc(str => Length(str))))
。
實際上,Unquote是專門為產生有用的單元測試斷言失敗消息而設計的,可以輕松地調試產生斷言失敗消息的斷言:
let inline Assert (q:Expr<bool>) =
#if DEBUG
System.Diagnostics.Debug.Assert(q.Eval(), q.ReduceFully() |> List.map (fun q -> q.Decompile()) |> String.concat System.Environment.NewLine)
#else
()
#endif
無論您要提出什么主張,都無法自動獲取失敗情況的文本表示。 最好的選擇是通過使用帶有消息的重載來顯式提供信息:
Debug.Assert(a = 10, "A should be 10")
如果您不必擔心Assert
的性能,則可以使用F#引用。 它們表示已編寫的代碼,可以對其進行評估(以測試斷言)並可以將其格式化為字符串:
#r @"C:\Programs\Development\PowerPack-2.0.0.0\bin\FSharp.PowerPack.Linq.dll"
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation
/// Assert that tests whether a quoted condition is true and throws
/// an exception containing a string representation of the code
let Assert (q:Expr<bool>) =
if not(q.Eval()) then failwithf "Assertion failed: %O" (q.ToLinqExpression())
let test() =
let a = 10
Assert <@ a = 11 @>
調用test
功能將給您以下消息。 調用ToLinqExpression
給您一個LINQ Expression
對象,該對象實現比F#引號更好的ToString
操作:
System.Exception:斷言失敗:(10 == 11)
C與F#完全不同。 C代碼必須留有足夠的面包屑,以使斷言消息有意義,以幫助您找出斷言在代碼中的何處。
在托管代碼中這不是問題。 您將獲得堆棧跟蹤,不需要字符串。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.