托管代码中的断言
断言(或 Assert
语句)测试您指定为 Assert
语句的参数的条件。 如果该条件的计算结果为 true,则不会执行任何操作。 如果条件的计算结果为 false,则断言失败。 如果运行的是调试生成,则程序会进入中断模式。
本主题内容
在 System.Diagnostics 命名空间中断言
在 Visual Basic 和 Visual C# 中,可使用位于 System.Diagnostics 命名空间中的 Debug 或 Trace 的 Assert
方法。 程序的发行版中不包含 Debug 类方法,因此它们不增大发行代码的大小,也不会减慢发行代码的速度。
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.Debug.Assert 的调用会增加发行版的开销。
Debug.Assert 的副作用
在使用 System.Diagnostics.Debug.Assert 时,确保 Assert
中的任何代码不会更改程序的结果(如果移除 Assert
)。 否则,可能会意外地引入一个只在程序的发行版中出现的 Bug。 对于包含函数或过程调用的断言要特别小心,如下面的示例:
乍一看,使用 System.Diagnostics.Debug.Assert 似乎很安全,但假设每次调用函数 meas 时,该函数都会更新计数器。 当生成发行版时,由于消除了对 meas 的调用,因此计数器将不会获得更新。 这是一个带副作用的函数的示例。 消除对具有副作用的函数的调用会导致一个只出现在发行版中的 Bug。 若要避免此类问题,请不要将函数调用放在 System.Diagnostics.Debug.Assert 语句中。 改用临时变量:
甚至在使用 System.Diagnostics.Trace.Assert 时,可能仍需要避免将函数调用置于 Assert
语句中。 这样的调用应是安全的,因为发行版中没有消除 System.Diagnostics.Trace.Assert 语句。 但是,如果习惯上避免这样的结构,则使用 System.Diagnostics.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++ 调试配置的项目设置。
断言自变量
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
方法将显示“断言失败”对话框。 断言失败时发生的操作由 Listeners 或 Listeners 属性控制。
可以通过向 TraceListener 集合添加 Listeners
对象、从 TraceListener 集合中移除 Listeners
或者重写现有 System.Diagnostics.TraceListener.Fail 的 TraceListener
方法来自定义输出行为,使其变得不同。
例如,可以替代 System.Diagnostics.TraceListener.Fail 方法来对事件日志进行写入而不是显示“断言失败”对话框。
若要通过此方式自定义输出,您的程序必须包含侦听器,并且必须从 TraceListener 继承并重写其 System.Diagnostics.TraceListener.Fail 方法。
有关详细信息,请参阅跟踪侦听器。
在配置文件中设置断言
你可以在程序配置文件和代码中设置断言。 有关详细信息,请参阅System.Diagnostics.Trace.Assert或System.Diagnostics.Debug.Assert。