到目前为止,我已经做了一年的专业软件工程师,并获得了计算机科学学位。我知道c++和C中的断言有一段时间了,但直到最近才知道它们存在于c#和。net中。
我们的生产代码不包含任何断言,我的问题是这个…
我应该开始在我们的生产代码中使用断言吗?如果可以,什么时候使用它最合适?这样做会更有意义吗
Debug.Assert(val != null, "message");
or
if ( val == null )
throw new exception("message");
到目前为止,我已经做了一年的专业软件工程师,并获得了计算机科学学位。我知道c++和C中的断言有一段时间了,但直到最近才知道它们存在于c#和。net中。
我们的生产代码不包含任何断言,我的问题是这个…
我应该开始在我们的生产代码中使用断言吗?如果可以,什么时候使用它最合适?这样做会更有意义吗
Debug.Assert(val != null, "message");
or
if ( val == null )
throw new exception("message");
当前回答
断言用于捕获程序员(您的)错误,而不是用户错误。只有在用户不可能触发断言时才应该使用它们。例如,如果你正在编写一个API,在API用户调用的任何方法中,都不应该使用断言来检查参数是否为空。但是它可以在一个私有方法中使用,而不是作为API的一部分公开,以断言您的代码永远不会在不应该传递null参数时传递null参数。
当我不确定时,我通常更喜欢异常而不是断言。
其他回答
将Debug.Assert()放在代码中任何需要进行完整性检查以确保不变量的地方。当编译Release版本时(即没有DEBUG编译器常量),对DEBUG . assert()的调用将被删除,因此它们不会影响性能。
在调用Debug.Assert()之前仍然应该抛出异常。断言只是确保在开发过程中一切都如预期的那样。
我不知道它在c#和。net中是怎样的,但在C中assert()只在使用- ddebug编译时工作-如果没有编译,最终用户将永远不会看到assert()。仅供开发人员使用。我经常使用它,它有时更容易跟踪错误。
摘自Code Complete (Wikipedia):
8 Defensive Programming 8.2 Assertions An assertion is code that’s used during development—usually a routine or macro—that allows a program to check itself as it runs. When an assertion is true, that means everything is operating as expected. When it’s false, that means it has detected an unexpected error in the code. For example, if the system assumes that a customer-information file will never have more than 50,000 records, the program might contain an assertion that the number of records is lessthan or equal to 50,000. As long as the number of records is less than or equal to 50,000, the assertion will be silent. If it encounters more than 50,000 records, however, it will loudly “assert” that there is an error in the program. Assertions are especially useful in large, complicated programs and in high reliability programs. They enable programmers to more quickly flush out mismatched interface assumptions, errors that creep in when code is modified, and so on. An assertion usually takes two arguments: a boolean expression that describes the assumption that’s supposed to be true and a message to display if it isn’t. (…) Normally, you don’t want users to see assertion messages in production code; assertions are primarily for use during development and maintenance. Assertions are normally compiled into the code at development time and compiled out of the code for production. During development, assertions flush out contradictory assumptions, unexpected conditions, bad values passed to routines, and so on. During production, they are compiled out of the code so that the assertions don’t degrade system performance.
如果我是你,我会这样做:
Debug.Assert(val != null);
if ( val == null )
throw new exception();
或者避免重复条件检查
if ( val == null )
{
Debug.Assert(false,"breakpoint if val== null");
throw new exception();
}
我想再添加四种情况,其中Debug。断言可以是正确的选择。
1)我在这里没有看到提到的是assert在自动化测试期间可以提供的额外概念覆盖。举个简单的例子:
当作者认为他们已经扩展了代码的范围以处理额外的场景,并修改了一些高级调用者时,理想情况下(!)他们将编写单元测试来覆盖这种新情况。那么,完全集成的代码可能会表现得很好。
然而,实际上已经引入了一个微妙的缺陷,但在测试结果中没有发现。在这种情况下,被调用者变得不确定,只提供预期的结果。或者,它产生了一个未被注意到的舍入误差。或者造成的错误在其他地方被抵消。或者不仅授予所请求的访问权限,还授予不应该授予的其他特权。等。
此时,被调用者中包含的Debug.Assert()语句加上单元测试驱动的新用例(或边缘用例)可以在测试期间提供宝贵的通知,即原始作者的假设已经失效,并且在没有额外审查的情况下不应该发布代码。断言与单元测试是完美的合作伙伴。
2)此外,有些测试写起来很简单,但成本很高,而且在初始假设下是不必要的。例如:
如果一个对象只能从某个安全的入口点访问,是否应该从每个对象方法对网络权限数据库进行额外查询,以确保调用者具有权限?当然不是。也许理想的解决方案包括缓存或其他一些功能扩展,但设计并不需要这样做。当对象被附加到不安全的入口点时,Debug.Assert()将立即显示。
3)其次,在某些情况下,当以发布模式部署时,您的产品可能对其全部或部分操作没有有用的诊断交互。例如:
Suppose it is an embedded real-time device. Throwing exceptions and restarting when it encounters a malformed packet is counter-productive. Instead the device may benefit from best-effort operation, even to the point of rendering noise in its output. It also may not have a human interface, logging device, or even be physically accessible by human at all when deployed in release mode, and awareness of errors is best provided by assessing the same output. In this case, liberal Assertions and thorough pre-release testing are more valuable than exceptions.
4)最后,有些测试是不必要的,只是因为被呼叫方被认为是非常可靠的。在大多数情况下,代码的可重用性越高,在使其可靠方面投入的精力就越多。因此,对于来自调用方的意外参数,通常使用Exception,而对于来自被调用方的意外结果,则使用Assert。例如:
If a core String.Find operation states it will return a -1 when the search criteria is not found, you may be able to safely perform one operation rather than three. However, if it actually returned -2, you may have no reasonable course of action. It would be unhelpful to replace the simpler calculation with one that tests separately for a -1 value, and unreasonable in most release environments to litter your code with tests ensuring core libraries are operating as expected. In this case Asserts are ideal.