簡體   English   中英

.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.

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