Nij*_*Nij 33 c# assert exception-handling
我刚刚开始浏览John Robbins的"调试MS .Net 2.0应用程序",并且因为他对Debug.Assert(...)的传福音而感到困惑.
他指出,良好实现的Asserts会在某种程度上存储错误状态,例如:
Debug.Assert(i > 3, "i > 3", "This means I got a bad parameter");
Run Code Online (Sandbox Code Playgroud)
现在,就个人而言,我似乎很疯狂,他如此喜欢在没有真正明智的"商业逻辑"评论的情况下重述他的测试,也许"因为flobittyjam widgitification过程,我必须永远不会发生i <= 3".
所以,我认为我认为Asserts是一种低级别的"让我保护我的假设"的东西......假设一个人认为这是一个只需要在调试中做的测试 - 即你保护自己不受同事的影响和未来的程序员,并希望他们实际测试的东西.
但是我没有得到的是,他继续说除了正常的错误处理之外你还应该使用断言; 现在我设想的是这样的:
Debug.Assert(i > 3, "i must be greater than 3 because of the flibbity widgit status");
if (i <= 3)
{
throw new ArgumentOutOfRangeException("i", "i must be > 3 because... i=" + i.ToString());
}
Run Code Online (Sandbox Code Playgroud)
我通过Debug.Assert重复错误条件测试获得了什么?如果我们谈论一个非常重要的计算的仅调试双重检查,我想我会得到它...
double interestAmount = loan.GetInterest();
Debug.Assert(debugInterestDoubleCheck(loan) == interestAmount, "Mismatch on interest calc");
Run Code Online (Sandbox Code Playgroud)
...但是我没有得到参数测试,这肯定值得检查(在DEBUG和Release版本中)......或者不是.我错过了什么?
Chr*_*ung 48
断言不适用于参数检查.应始终进行参数检查(并且精确地根据文档和/或规范中指定的前提条件),并ArgumentOutOfRangeException根据需要进行抛出.
断言用于测试"不可能"的情况,即(在程序逻辑中)假设的事情是真的.断言是告诉你这些假设是否因任何原因被破坏.
希望这可以帮助!
hwi*_*ers 17
断言与异常抛出有沟通方面.
假设我们有一个带有Name属性和ToString方法的User类.
如果ToString是这样实现的:
public string ToString()
{
Debug.Assert(Name != null);
return Name;
}
Run Code Online (Sandbox Code Playgroud)
它表示Name应该永远不会为null,如果是,则User类中存在错误.
如果ToString是这样实现的:
public string ToString()
{
if ( Name == null )
{
throw new InvalidOperationException("Name is null");
}
return Name;
}
Run Code Online (Sandbox Code Playgroud)
它表示如果Name为null,调用者正在使用ToString,并且应该在调用之前检查它.
两者的实施
public string ToString()
{
Debug.Assert(Name != null);
if ( Name == null )
{
throw new InvalidOperationException("Name is null");
}
return Name;
}
Run Code Online (Sandbox Code Playgroud)
如果Name为null,那么User类中会出现bug,但我们还是要处理它.(用户在打电话之前不需要检查姓名.)我认为这是罗宾斯推荐的那种安全措施.
在提供关于测试问题的调试与断言的指导时,我已经考虑过这个漫长而艰难的过程.
您应该能够使用错误的输入,错误的状态,无效的操作顺序以及任何其他可能的错误条件来测试您的类,并且断言永远不会跳闸.每个断言都在检查一些事情应该始终为真,无论输入或计算是什么.
我已经达到了良好的经验法则:
断言不能替代能够正确独立于配置运行的健壮代码.它们是互补的.
在单元测试运行期间,即使在输入无效值或测试错误条件时,断言也不应跳闸.代码应该处理这些条件而不会发生断言.
如果断言跳闸(在单元测试中或在测试期间),则会对该类进行窃听.
对于所有其他错误 - 通常是环境(网络连接丢失)或误用(调用者传递空值) - 使用硬检查和异常会更好,更容易理解.如果发生异常,则调用者知道它可能是他们的错.如果发生断言,则调用者知道它可能是断言所在代码中的错误.
关于重复:我同意.我不明白为什么你会用Debug.Assert和异常检查来复制验证.它不仅会给代码增加一些噪音,而且还会让人感到困惑,因为这是一种重复的形式.