我今天应该仍然使用Debug.Assert吗?


23

我最近遇到了一些新编写的代码,这些代码中散布着许多Debug.Assert(C#)。

尽管总体上使用了TDD,BDD和单元测试,我们是否仍应广泛使用它?


9
我看不到一个人如何排除另一个人。
superM 2013年

2
@superM我肯定已经看到懒惰的开发人员在编写代码之前就将测试添加为断言,因为这样很难模拟出依赖关系。不用说,我不会推荐
JK。

Answers:


23

我看不出您不应该使用Assert的任何原因。通过这样做,您已经认识到需要警卫(例如前提条件和不变式),并且正在朝着“ 按合同设计”的方向发展。断言只是实现这一目标的一种方法...

// Precondition using Asert
void SomeMethod(Foo someParameter)
{
    Debug.Assert(someParameter != null)
}

// Precondition using If-Then-Throw
void SomeMethod(Foo someParameter)
{
    if (someParameter == null)
        throw new ArgumentNullException("someParameter");
}

// Precondition using Code Contracts
void SomeMethod(Foo someParameter)
{
    Contract.Requires(someParameter != null);
}

// Precondition using some custom library
void SomeMethod(Foo someParameter)
{
    Require.ArgumentNotNull(() => someParameter);
}

都是实现同一目标的方法:代码的健壮性。它仅取决于选择一个选项,其中Assert是有效的选择。

请注意,到目前为止,我还没有提到单元测试,因为它们可以完成非常不同的事情。单元测试通过行使保护措施来正式证明代码的健壮性:

[Test]
void SomeMethod_WhenGivenNull_ThrowsArgumentNullException()
{
    delegate call = () => someObject.SomeMethod(null);

    Assert.That(call).Throws<ArgumentNullException>();
}

这是完全不同的断言...

**请注意,在某些框架中,对于断言失败进行单元测试实际上是相当困难的,因为断言失败会降低整个运行时间,因此可能更希望使用其他选项之一... *


10

我认为断言和单元测试是我工具箱中的两个不同工具。有些东西更适合其中一种,而有些则更适合另一种。

举例来说,如今,我主要使用断言来验证非公共方法的参数。


5

我现在将Debug.Assert视为过早的优化。除非您真的需要性能,否则禁止在发布模式下声明“ Assert”可以将错误隐藏的时间更长。

正如MattDavey指出的那样,代码契约可以提供静态检查而不是动态检查,这是一个更好的选择,如果不可用,我更喜欢使用Trace.Assert或简单的旧代码。if(x) throw SomeException;


4
值得一提的是,在发布模式下使用Visual Studio生成代码将导致对Debug类方法的所有调用都从编译中跳过……因此,Assert仅出于性能考虑而抑制调用不只是过早的优化,这是胡说八道。
Konamiman

重点是@Konamiman,我几乎总是希望它在发布模式下以相同的方式失败:Debug.Assert对我97%的时间毫无用处
jk。

那@jk那是3%那是什么?仅是遗留代码还是其他实例?
DougM 2014年

@DougM性能关键代码,它是对knuth引用的引用。我还想补充一点,我觉得心脏出血漏洞错误表明我的看法是正确的,除非你有没有其他选择,没有前提的Elid在检查你的发布代码
JK。
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.