Ошибка отображения состояния .net с - PullRequest
1 голос
/ 18 мая 2011

ОК, я привык к старым добрым утверждениям C, когда они терпят неудачу, они выводят условие, в котором они потерпели неудачу, и строку, в которой оно было. (реализовано с препроцессором).

Теперь я программирую на F # (язык .net), получил полный код assert. (пытается программировать оборонительно). и мои активы показывают всплывающее окно со стеком вызовов. в соответствии с документация также может передавать строку assert для отображения в случае сбоя. чтобы я мог передать ему строковую копию моего состояния. например:

assert (x=true, "x=true")

но это нарушает принцип Дублирования (избегая).

Если позже я решу изменить то, что хочу утверждать. (возможно, я понял, что утверждаю что-то как ложное, когда должен был утверждать, что это правда), тогда мне нужно изменить код в двух местах, иначе сообщение не будет соответствовать тому, что я проверяю. и если я забуду, что-то может сбить с толку.

Как с этим обычно справляются?

Ответы [ 3 ]

5 голосов
/ 18 мая 2011

Повторяя сказанное Томасом, вы можете использовать цитаты, чтобы избежать дублирования. Но вместо ToLinqExpression -> ToString, который, очевидно, создает исходный код C #, вы можете использовать мою библиотеку Unquote , которая создает строки исходного кода F #. Объедините это с реализацией, подходящей для производственного кода (т. Е. Определяя Assert inline с ветвью символа компиляции, отличной от DEBUG, испускающей только no-op () означает, что использование Assert будет полностью удалено в non-DEBUG сборка с включенной оптимизацией):

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):

enter image description here

Где для сравнения 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

enter image description here

4 голосов
/ 18 мая 2011

Независимо от того, о чем вы спрашиваете, нет способа автоматически получить текстовое представление о том, что условие не выполнено.Лучший вариант - предоставить информацию явно, используя перегрузку, которая принимает сообщение:

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, который реализует более приятную ToString операцию, чем цитаты F #:

System.Exception: Утверждение не удалось: (10 == 11)

2 голосов
/ 18 мая 2011

Это полностью отличается в C против F #.Код C должен оставлять достаточно крошек, чтобы сообщение с подтверждением было достаточно значимым, чтобы помочь вам выяснить, где в коде ваше утверждение не удалось.

Это не проблема в управляемом коде.Вы получаете трассировку стека, нет необходимости в строке.

...