托管代码中的断言

断言(或 Assert 语句)测试您指定为 Assert 语句的参数的条件。 如果该条件的计算结果为 true,则不会执行任何操作。 如果条件的计算结果为 false,则断言失败。 如果运行的是调试生成,则程序会进入中断模式。

本主题内容

System.Diagnostics 命名空间中的断言

Debug.Assert 方法

Debug.Assert 的副作用

跟踪和调试需求

断言参数

自定义断言行为

在配置文件中设置断言

在 System.Diagnostics 命名空间中断言

在 Visual Basic 和 Visual C# 中,可使用位于 System.Diagnostics 命名空间中的 DebugTraceAssert 方法。 程序的发行版中不包含 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。 对于包含函数或过程调用的断言要特别小心,如下面的示例:

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

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

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

甚至在使用 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.AssertSystem.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)

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

第二个和第三个自变量(如果有)必须是字符串。 如果调用带有两个或三个自变量的 System.Diagnostics.Trace.AssertSystem.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 方法将显示“断言失败”对话框。 断言失败时发生的操作由 ListenersListeners 属性控制。

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

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

若要通过此方式自定义输出,您的程序必须包含侦听器,并且必须从 TraceListener 继承并重写其 System.Diagnostics.TraceListener.Fail 方法。

有关详细信息,请参阅跟踪侦听器

在本主题中

在配置文件中设置断言

你可以在程序配置文件和代码中设置断言。 有关详细信息,请参阅System.Diagnostics.Trace.AssertSystem.Diagnostics.Debug.Assert