托管代码中的断言

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

主题内容

在 System.Diagnostics 命名空间中断言

Debug.Assert 方法

Debug.Assert 的副作用

跟踪和调试要求

断言参数

自定义断言行为

在配置文件中设置断言

在 System.Diagnostics 命名空间中断言

在 Visual Basic 和 Visual C# 中,可以使用 DebugTrace(二者位于 System.Diagnostics 命名空间中)中的 Assert 方法。 程序的发行版中不包含 Debug 类方法,因此它们不增大发行代码的大小,也不会减慢发行代码的速度。

C++ 不支持 Debug 类方法。 可将 Trace 类与条件编译(如 #ifdef DEBUG...)一起使用来达到相同的效果。 #endif.

主题内容

Debug.Assert 方法

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

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 方法的调用将消失。 这意味着,检查余额的调用将在发行版本中消失。 若要解决此问题,您应将 Debug.Assert 替换为在发行版中不会消失的 Trace.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 时犯错的可能性会很小。

主题内容

跟踪和调试要求

如果使用 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 方法,您必须在“发布”配置中定义 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 项目类型

调试托管代码