托管代码中的断言

断言(或 Assert 语句)测试您作为 Assert 语句的参数指定的条件。 如果此条件计算为 true,不发生操作。 如果此条件计算为 false,则断言失败。 如果正在调试版本中运行,则程序进入中断模式。

主题内容

在 System.Diagnostics 命名空间断言

Debug.Assert 方法

Debug.Assert 副作用

Trace 和 Debug 的要求

断言参数

自定义断言行为

在配置文件中设置断言

在 System.Diagnostics 命名空间断言

在 Visual Basic 和 Visual C# 中,可以使用方法调用,可以从 System.Diagnostics 命名空间下的 DebugTrace 调用 Assert 方法。 在您的程序的发布版本中不包含 Debug 类方法,因此它们不增大或减小发布代码的速度。

C++ 不支持 Debug 类方法。 使用带有条件编译的 Trace 类(如 #ifdef DEBUG...)可获得同样的效果。 #endif.

主题内容

Debug.Assert 方法

可随意使用 Debug.Assert 方法测试条件,如果代码正确,该条件应保持为真。 例如,假设已编写一个整数除法函数。 根据数学规则,除数永远不能为零。 可以使用断言测试该条件:

Function IntegerDivide(ByVal dividend As Integer, ByVal divisor As Integer) As Integer
    Debug.Assert(divisor <> 0)
    Return CInt(dividend / divisor)
End Function
int IntegerDivide ( int dividend , int divisor )
    { Debug.Assert ( divisor != 0 );
        return ( dividend / divisor ); }

当在调试器下运行该代码时,将计算断言语句,但是在发行版本中,将不进行该比较,因此没有额外的系统开销。

以下是另一个示例。 您有一个实现支票活期存款帐户的类,如下所示:

Dim amount, balance As Double
balance = savingsAccount.balance
Debug.Assert(amount <= balance)
SavingsAccount.Withdraw(amount)
float balance = savingsAccount.Balance;
Debug.Assert ( amount <= balance );
savingsAccount.Withdraw ( amount );

在从该帐户中提取钱之前,您想要确保帐户的余额大于准备取出的金额。 可以编写检查余额的断言:

Dim amount, balance As Double
balance = savingsAccount.balance
Trace.Assert(amount <= balance)
SavingsAccount.Withdraw(amount)
float balance = savingsAccount.Balance;
Trace.Assert ( amount <= balance );
savingsAccount.Withdraw ( amount );

注意,当创建代码的发行版本时,对 Debug.Assert 方法的调用将消失。 这意味着在发行版本中检查余额的调用将消失。 若要解决此问题,您应使用不会在发行版本中消失的 Trace.Assert 替换 Debug.Assert

与对 Debug.Assert 的调用不同,对 Trace.Assert 的调用会增加发行版本的系统开销。

主题内容

Debug.Assert 副作用

使用 Debug.Assert 时,确保 Assert 中的任何代码不会更改程序的结果(如果移除 Assert)。 否则,可能会意外地引入一个只在程序的发行版本中出现的 bug。 对于包含函数或过程调用的断言要特别小心,如下面的示例:

' unsafe code
Debug.Assert (meas(i) <> 0 )
// unsafe code
Debug.Assert (meas(i) != 0 );

乍一看,使用 Debug.Assert 似乎很安全,但是假设每次调用函数 meas 时该函数都会更新计数器。 当生成发行版本时,由于消除了对 meas 的调用,因此计数器将得不到更新。 这是一个带“副作用”的函数的示例。 消除对具有副作用的函数的调用会导致一个只出现在发行版本中的 bug。 为避免这样的问题,请不要将函数调用放在 Debug.Assert 语句中。 改用临时变量:

temp = meas( i )
Debug.Assert (temp <> 0)
temp = meas( i );
Debug.Assert ( temp != 0 );

即使在使用 Trace.Assert 时,也需要避免将函数调用放置到 Assert 语句中。 这样的调用应是安全的,因为在发行版本中没有消除 Trace.Assert 语句。 但是,如果习惯上避免这样的结构,则使用 Debug.Assert 时犯错误的可能性很小。

主题内容

Trace 和 Debug 的要求

如果使用 Visual Studio 向导创建项目,则默认情况下,“发布”配置和“调试”配置中都定义了 TRACE 符号。 默认情况下,只在调试版本中定义 DEBUG 符号。

否则,若要使 Trace 方法工作,程序必须在源文件的顶部放置以下代码之一:

  • Visual Basic 中的 #Const TRACE = True

  • Visual C# 和 C++ 中的 #define TRACE

或者,程序必须是用 TRACE 选项生成的:

  • Visual Basic 中的 /d:TRACE=True

  • Visual C# 和 C++ 中的 /d:TRACE

如果需要在 C# 或 Visual Basic 发行版本中使用 DEBUG 方法,必须在“Release”配置中定义 DEBUG 符号。

C++ 不支持 Debug 类方法。 使用带有条件编译的 Trace 类(如 #ifdef DEBUG...)可获得同样的效果。 #endif. 可以在**“<项目> 属性页”**对话框中定义这些符号。 有关更多信息,请参见为 Visual Basic 调试配置更改项目设置更改 C 或 C++ 调试配置的项目设置

断言参数

Trace.AssertDebug.Assert 最多有三个参数。 第一个参数是强制的,它是想要检查的条件。 如果仅用一个参数来调用 Trace.Assert(Boolean)Debug.Assert(Boolean),Assert 方法将检查条件,并且如果结果是 false,则向**“输出”**窗口输出调用堆栈的内容。 下面的示例显示 Trace.Assert(Boolean)Debug.Assert(Boolean)

Debug.Assert(stacksize > 0)
Trace.Assert(stacksize > 0)
Debug.Assert ( stacksize > 0 );
Trace.Assert ( stacksize > 0 ); 

第二个和第三个参数(如果有)必须是字符串。 如果调用带有两个或三个参数的 Trace.AssertDebug.Assert,则第一个参数是一个条件。 该方法检查此条件,如果结果为 false,则输出第二个和第三个字符串。 下面的示例演示 Debug.Assert(Boolean, String)Trace.Assert(Boolean, String) 使用两个参数的情况:

Debug.Assert(stacksize > 0, "Out of stack space")
Trace.Assert(stacksize > 0, "Out of stack space")
Debug.Assert ( stacksize > 0, "Out of stack space" );
Trace.Assert ( stacksize > 0, "Out of stack space" );

下面的示例显示 AssertAssert

Debug.Assert(stacksize > 0, "Out of stack space. Bytes left:" , Format(size, "G"))
Trace.Assert(stacksize > 0, "Out of stack space. Bytes left:" , Format(size, "G"))
Trace.Assert(stacksize > 0, "Out of stack space. Bytes left:", "inctemp failed on third call" )
Debug.Assert ( stacksize > 100, "Out of stack space" , "Failed in inctemp" );
Trace.Assert ( stacksize > 0, "Out of stack space", "Failed in inctemp" ); 

主题内容

自定义断言行为

如果在用户界面模式中运行应用程序,则当条件失败时,Assert 方法将显示**“断言失败”**对话框。 发生的事件,当断言失败由 ListenersListeners 属性控制。

可以通过向 Listeners 集合添加 TraceListener 对象、从 Listeners 集合移除 TraceListener 或者重写现有 TraceListener 的 TraceListener.Fail 方法来自定义输出行为,使其行为不同。

例如,可以重写 TraceListener.Fail 方法来写入事件日志而不是显示**“断言失败”**对话框。

若要以这种方法自定义输出,则程序必须包含侦听器,并且必须从 TraceListener 继承并重写它的 TraceListener.Fail 方法。

有关更多信息,请参见跟踪侦听器

主题内容

在配置文件中设置断言

您可以在程序配置文件和代码中设置断言。 有关更多信息,请参见Trace.AssertDebug.Assert

请参见

任务

如何:使用跟踪和调试进行条件编译

参考

Debug.Assert

Trace.Assert

概念

调试器安全

其他资源

跟踪应用程序和在应用程序中插入检测点

调试准备:C#、F# 和 Visual Basic 项目类型

调试托管代码