断言(或 Assert
语句)测试一个你指定为 Assert
语句的自变量的条件。 如果该条件的计算结果为 true,则不会执行任何操作。 如果条件的计算结果为 false,则断言失败。 如果运行的是调试生成,则程序会进入中断模式。
在本主题中
System.Diagnostics 命名空间中的断言
在 Visual Basic 和 Visual C# 中,可以使用Assert
方法,这些方法来自 Debug 或 Trace,它们位于 System.Diagnostics 命名空间中。
Debug 类方法未包含在程序的 Release 版本中,因此它们不会增加大小或降低发布代码的速度。
C++不支持 Debug 类方法。 可以通过将类与条件编译一起使用来实现相同的效果 Trace ,例如 #ifdef DEBUG
... #endif
。
Debug.Assert 方法
自由使用 System.Diagnostics.Debug.Assert 方法来测试代码正确时应为 true 的条件。 例如,假设你已编写整数除法函数。 根据数学规则,除数绝不能为零。 可以使用断言对此进行测试:
int IntegerDivide ( int dividend , int divisor )
{
Debug.Assert ( divisor != 0 );
return ( dividend / divisor );
}
在调试器下运行此代码时,将评估断言语句,但在发布版本中,不会进行比较,因此没有额外的开销。
下面是另一个示例。 你有一个实现支票账户的类,如下所示:
float balance = savingsAccount.Balance;
Debug.Assert ( amount <= balance );
savingsAccount.Withdraw ( amount );
在从帐户提取资金之前,你需要确保帐户余额足以支付准备提取的金额。 可以编写断言来检查余额:
float balance = savingsAccount.Balance;
Trace.Assert ( amount <= balance );
savingsAccount.Withdraw ( amount );
请注意,在创建代码的发布版本时,对 System.Diagnostics.Debug.Assert 方法的调用将消失。 这意味着检查余额的调用在发布版本中消失。 若要解决此问题,应把System.Diagnostics.Debug.Assert替换为System.Diagnostics.Trace.Assert,这样System.Diagnostics.Trace.Assert在发布版本中不会消失。
调用 System.Diagnostics.Trace.Assert 会增加发布版本的开销,这与调用 System.Diagnostics.Debug.Assert不同。
Debug.Assert 的副作用
使用 System.Diagnostics.Debug.Assert时,请确保内部 Assert
的任何代码都不会更改程序的结果(如果 Assert
已删除)。 否则,可能会意外引入只有在程序的发布版本中才会出现的 bug。 请特别小心包含函数或过程调用的断言,如以下示例:
这种使用 System.Diagnostics.Debug.Assert 可能看起来很安全,但假设每次调用函数时,函数 meas 都会更新计数器。 生成发布版本时,将消除对 meas 的此调用,因此计数器不会更新。 这是具有副作用的函数的示例。 消除对具有副作用的函数的调用可能会导致仅出现在 Release 版本中的 bug。 为了避免此类问题,请不要在语句中 System.Diagnostics.Debug.Assert 放置函数调用。 请改用临时变量:
即使使用 System.Diagnostics.Trace.Assert,你可能仍希望避免在 Assert
语句中放置函数调用。 此类调用应该是安全的,因为 System.Diagnostics.Trace.Assert 发布版本中不会消除语句。 但是,如果你避免这种构造作为习惯问题,你不太可能在使用 System.Diagnostics.Debug.Assert时犯错误。
跟踪和调试要求
如果使用 Visual Studio 向导创建项目,则默认情况下会在“发布”和“调试”配置中定义 TRACE 符号。 调试符号默认仅在调试版本中定义。
否则,若要Trace方法正常工作,你的程序必须在源文件顶部包含以下选项之一:
#Const TRACE = True
在 Visual Basic 中#define TRACE
在 Visual C# 和 C++或者您的程序必须使用 TRACE 选项编译:
/d:TRACE=True
在 Visual Basic 中/d:TRACE
在 Visual C# 和 C++如果需要在 C# 或 Visual Basic 发布版本中使用 Debug 方法,则必须在发布配置中定义 DEBUG 符号。
C++不支持 Debug 类方法。 可以通过将类与条件编译一起使用来实现相同的效果 Trace ,例如
#ifdef DEBUG
...#endif
。 可以在“项目>属性页”对话框中定义这些符号<。 有关详细信息,请参阅 更改 Visual Basic 调试配置的项目设置 或更改 C 或C++调试配置的项目设置。
断言参数
System.Diagnostics.Trace.Assert 和 System.Diagnostics.Debug.Assert 可以接受最多三个参数。 第一个参数是必需的,它是您想要检查的条件。 如果调用 System.Diagnostics.Trace.Assert(Boolean) 或 System.Diagnostics.Debug.Assert(Boolean) 仅使用一个参数,该方法 Assert
将检查条件,如果结果为 false,则将调用堆栈的内容输出到 “输出 ”窗口。 以下示例演示 System.Diagnostics.Trace.Assert(Boolean) 和 System.Diagnostics.Debug.Assert(Boolean):
第二个和第三个参数(如果存在)必须是字符串。 如果调用 System.Diagnostics.Trace.Assert 或 System.Diagnostics.Debug.Assert 具有两个或三个参数,则第一个参数是一个条件。 该方法检查条件,如果结果为 false,则输出第二个字符串和第三个字符串。 以下示例展示了 System.Diagnostics.Debug.Assert(Boolean, String) 和 System.Diagnostics.Trace.Assert(Boolean, String) 使用两个参数的情况:
Debug.Assert ( stacksize > 0, "Out of stack space" );
Trace.Assert ( stacksize > 0, "Out of stack space" );
以下示例演示了 System.Diagnostics.Debug.Assert(Boolean, String, String) 和 System.Diagnostics.Trace.Assert(Boolean, String, String) 与三个参数一起使用的情况:
Debug.Assert ( stacksize > 100, "Out of stack space" , "Failed in inctemp" );
Trace.Assert ( stacksize > 0, "Out of stack space", "Failed in inctemp" );
自定义 Assert 行为
如果在用户界面模式下运行应用程序,该方法 Assert
将在条件失败时显示 “断言失败 ”对话框。 断言失败时发生的作由 Listeners 或 Listeners 属性控制。
可以通过向Listeners
集合中添加TraceListener对象、从Listeners
集合中删除TraceListener对象,或者重写现有TraceListener
的System.Diagnostics.TraceListener.Fail方法来改变其行为,从而自定义输出行为。
例如,可以重写 System.Diagnostics.TraceListener.Fail 方法以写入事件日志,而不是显示 断言失败 对话框。
若要以这种方式自定义输出,您的程序必须包含一个侦听器,并且要从TraceListener继承并重写其System.Diagnostics.TraceListener.Fail方法。
有关详细信息,请参阅 跟踪侦听器。
在配置文件中设置断言
可以在程序配置文件和代码中设置断言。 有关详细信息,请参阅 System.Diagnostics.Trace.Assert 或 System.Diagnostics.Debug.Assert。