Visual Studio 调试器 托管代码中的断言

来源:互联网 发布:网络作家苍白的黑夜 编辑:程序博客网 时间:2024/04/28 16:01

Visual Studio 调试器 托管代码中的断言

 (2008-05-29 00:20)
  • 标签: -  分类: .NET
Visual Studio 调试器
托管代码中的断言

 

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

在 Visual Basic 和 Visual C# 中,可以从 Debug 或 Trace 中使用 Assert 方法,这两种方法都在 System.Diagnostics 命名空间中。由于 Debug 类方法未包含在程序的“发布”版本中,所以它们不会增加发布代码的大小或降低其速度。

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

16x16 Debug.Assert 方法

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

[Visual Basic]

Function IntegerDivide(ByVal dividend As Integer, ByVal divisor As Integer) As Integer Debug.Assert(divisor <> 0) Return CInt(dividend / divisor) End Function

[C#]

int IntegerDivide ( int dividend , int divisor ) { Debug.Assert ( divisor != 0 ); return ( dividend / divisor ); }

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

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

[Visual Basic]

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

[C#]

float balance = savingsAccount.Balance; Debug.Assert ( amount <= balance ); savingsAccount.Withdraw ( amount );

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

[Visual Basic]

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

[C#]

float balance = savingsAccount.Balance; Trace.Assert ( amount <= balance ); savingsAccount.Withdraw ( amount );

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

与对 System.Diagnostics.Debug.Assert(System.Boolean) 的调用不同,对System.Diagnostics.Trace.Assert(System.Boolean) 的调用会增加发布版本的系统开销。

16x16 Debug.Assert 的副作用

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

[Visual Basic]

' unsafe code Debug.Assert (meas(i) <> 0 )

[C#]

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

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

[Visual Basic]

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

 

[C#]

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

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

16x16 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 可以在“<Project> 属性页”对话框中定义这些符号。有关更多信息,请参见为 Visual Basic 调试配置更改项目设置或更改 C 或 C++ 调试配置的项目设置。)

16x16 Assert 参数

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

[Visual Basic]

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

[C#]

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

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

[Visual Basic]

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

[C#]

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

下面的示例显示 Assert 和 Assert

[Visual Basic]

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" )

[C#]

Debug.Assert ( stacksize > 100, "Out of stack space" , "Failed in inctemp" );Trace.Assert ( stacksize > 0, "Out of stack space", "Failed in inctemp" );
16x16 自定义 Assert 行为

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

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

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

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

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

16x16 在配置文件中设置断言

您可以在程序配置文件和代码中设置断言。有关更多信息,请参见System.Diagnostics.Trace.Assert(System.Boolean) 或System.Diagnostics.Debug.Assert(System.Boolean)

原创粉丝点击