C#-Assert()方法做什么?它仍然有用吗?


Answers:


200

在调试编译中,Assert将布尔条件作为参数,如果条件为假,则显示错误对话框。如果条件为真,程序将继续运行而不会中断。

如果您在Release中编译,则所有Debug.Assert都将自动被忽略。


12
如何在发布模式下获得相同的Debug.Assert行为?
Hamish Grubijan 2011年


8
@HamishGrubijan为什么要Debug.Assert在发布模式下?
卡米洛·马丁

25
IMO忽略了发布代码中的断言,就像在停泊时进行救生艇演习,然后在航行时将救生艇抛在身后。:)
chrisd 2012年

113
断言不是救生艇,而是冰山探测系统。由于用户没有驾船,释放代码中的断言只会告诉他们他们注定要失败。它不能让他们避开冰山。
Stefan

97

代码完成

8防御性编程

8.2断言

断言是在开发过程中使用的代码(通常是例程或宏),它使程序可以在运行时进行自我检查。当断言为真时,这意味着一切都按预期进行。如果为假,则表示已在代码中检测到意外错误。例如,如果系统假定客户信息文件的记录永远不会超过50,000条,则该程序可能包含断言,即记录数小于或等于50,000。只要记录数小于或等于50,000,则断言将保持沉默。但是,如果遇到超过50,000条记录,它将大声“断言”程序中存在错误。

断言在大型,复杂程序和高可靠性程序中特别有用。它们使程序员能够更快地清除不匹配的接口假设,修改代码时产生的错误等等。

断言通常带有两个参数:一个布尔表达式,描述应该为真的假设;否则,显示一条消息。

(...)

通常,您不希望用户在生产代码中看到断言消息。断言主要用于开发和维护期间。断言通常在开发时编译到代码中,并从代码中编译出来用于生产。在开发过程中,断言消除了矛盾的假设,意外情况,传递给例程的错误值等。在生产过程中,它们是用代码编译的,因此断言不会降低系统性能。


2
《编写固体代码》一书也对assert的用法进行了很好的讨论。他们是一个很棒的调试工具!
zooropa '16

39

您应该在不需要断行每一行代码来检查变量的时候使用它,但是如果确实存在某些情况,您确实希望获得某种反馈,例如:

Debug.Assert(someObject != null, "someObject is null! this could totally be a bug!");

如果我添加与上面的代码相似的代码行,则运行我的程序将出现以下错误:“错误CS0103:名称“ Debug”在当前上下文中不存在”。我需要某种使用语句来使其工作吗?
Josh Desmond

4
@JoshDesmondSystem.Diagnostics
Sinjai

16

Assert还为您提供了另一个机会来嘲笑Microsoft的UI设计技能。我的意思是:带有三个按钮的对话框:中止,重试,忽略,以及在标题栏中说明如何解释它们!


3
中止/重试/忽略是经典!是曾经导致Windows 3.1一直显示此内容的断言吗?
08年

基本上是因为它使用了一个MessageBox,正如您所说的,它可以追溯到Windows 3.1,并且只有预定义的按钮标签。因此,您可以了解为什么会发生这种黑客入侵,但不能理解为什么它在2008年仍然存在!

4
@Joe这是开发人员而不是最终用户应该看到的东西,因此更新它可能是一个优先级极低的项目。如果麻烦的话,您可以修改Debug.Listeners或Trace.Listeners集合以将默认处理程序替换为可以执行所需操作的默认处理程序。
Dan在火光中摆弄2011年

5
好吧,现在是2019年,相同的对话框/按钮仍在这里!
布克

10

断言允许您断言在代码中适用的条件(发布后或发布前)。这是记录您的意图并让调试器通过对话框通知您的方法,如果您的意图没有得到满足。

与断点不同,断言与您的代码一起使用,可用于添加有关您的意图的其他详细信息。


10

断言可以帮助您在测试和发布之间给出单独的消息传递行为。例如,

Debug.Assert(x > 2)

仅在运行“调试”版本而不是发行版本时才会触发中断。有此行为的完整的例子在这里


10

首先,Assert()方法可用于TraceDebug类。
Debug.Assert()仅在调试模式下执行。
Trace.Assert()在调试和发布模式下执行。

这是一个例子:

        int i = 1 + 3;
        // Debug.Assert method in Debug mode fails, since i == 4
        Debug.Assert(i == 3);
        Debug.WriteLine(i == 3, "i is equal to 3");

        // Trace.Assert method in Release mode is not failing.
        Trace.Assert(i == 4);
        Trace.WriteLine(i == 4, "i is equla to 4");

        Console.WriteLine("Press a key to continue...");
        Console.ReadLine();

在调试模式下然后在发布模式下运行此代码。

在此处输入图片说明

您会注意到,在调试模式下,您的代码Debug.Assert语句失败,您将看到一个消息框,其中显示了应用程序的当前堆栈跟踪。由于Trace.Assert()condition为true,因此在Release模式下不会发生这种情况(i == 4)

WriteLine() 方法只是为您提供了将信息记录到Visual Studio输出的选项。 在此处输入图片说明


5

断言在按合同设计(DbC)中占有重要地位,据我所知,它是由Bertand的Meyer引入/认可的。1997。面向对象的软件构造。

一个重要的功能是它们一定不能产生副作用,例如,您可以使用if语句(防御性编程)来处理异常或采取其他措施。

断言用于检查合同的前/后条件,客户/供应商关系-客户必须确保满足供应商的前提条件,例如。发送5英镑,供应商必须确保满足后置条件,例如 提供12朵玫瑰。(对客户/供应商的简单说明-可以接受较少的内容并提供更多的内容,但是有关断言)。C#还引入了Trace.Assert(),可用于发布代码。

要回答这个问题,它们仍然有用,但是会增加代码的复杂度和可读性,并增加维护时间和难度。我们还应该使用它们吗?是的,我们都会使用它们吗?可能不是,或者没有达到Meyer描述的程度。

(即使我学习过此技术的OU Java课程也仅显示了简单的示例,而该代码中的其余代码并未对大多数代码强制执行DbC断言规则,但被假定为可确保程序正确性!)


3

我认为的方法是Debug.Assert,它是一种建立关于应如何调用方法的协定的方法,着重于参数值(而不是类型)的细节。例如,如果不应该在第二个参数中发送null,则在该参数周围添加Assert,以告知使用者不要这样做。

它可以防止他人以笨拙的方式使用您的代码。但是,它也允许这种笨拙的方式进入生产环境,并且不会向客户发出令人讨厌的消息(假设您构建了Release版本)。


6
但是,必须指出,公共方法上的无效参数应引发参数异常。仅私有方法应使用断言来验证输入。来自外部的价值总是值得怀疑的!
Jeffrey L Whitledge,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.