.net断言显示条件失败

Lyn*_*ite 1 .net f# assert visual-studio-2010

好吧,我已经习惯了旧的C断言,当它们失败时,它们会输出它们失败的条件,以及它所在的线路.(与预处理器一起使用).

现在我用F#编程(一种.net语言),代码充满了断言.(尝试防御性地编程).我的资产显示了一个带调用堆栈的弹出窗口.根据文档,也可以传递断言字符串,以便在失败时显示.所以我可以通过我的条件的字符串副本.例如:

assert (x=true, "x=true")
Run Code Online (Sandbox Code Playgroud)

但这违反了复制(避免)委托人.

如果我后来决定改变我想要断言的东西.(也许我意识到当我应该断言它是真的时我声称某些东西是假的)然后我必须在两个地方更改代码,否则消息将与我实际检查的内容不匹配.如果我忘记了事情可能会让人感到困惑.

这通常是如何处理的?

Ste*_*sen 5

与Tomas所说的相呼应,您可以使用引用来避免重复.但是,而不是ToLinqExpression -> ToString,显然产生C#源代码,你可以使用我的库Unquote生成F#源代码字符串.将此与适用于生产代码的实现相结合(即Assert,使用非DEBUG编译符号分支进行内联定义仅发出no-op ()意味着Assert将在非DEBUG构建中完全删除使用,并且启用优化):

let inline Assert (q:Expr<bool>) =
    #if DEBUG
        System.Diagnostics.Debug.Assert(q.Eval(), q.Decompile())
    #else
        ()
    #endif
Run Code Online (Sandbox Code Playgroud)

然后断言表达式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
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述