定期验证我的函数参数:
public static void Function(int i, string s)
{
Debug.Assert(i > 0);
Debug.Assert(s != null);
Debug.Assert(s.length > 0);
}
当然,检查在函数的上下文中是“有效的”。
这是常见的行业惯例吗?有关函数参数验证的常见做法是什么?
答案 0 :(得分:10)
如果值无效或以后会导致异常,则接受的做法如下:
if( i < 0 )
throw new ArgumentOutOfRangeException("i", "parameter i must be greater than 0");
if( string.IsNullOrEmpty(s) )
throw new ArgumentNullException("s","the paramater s needs to be set ...");
所以基本参数例外列表如下:
ArgumentException ArgumentNullException ArgumentOutOfRangeException
答案 1 :(得分:5)
您撰写的内容是先决条件,以及按合同设计中的基本要素。谷歌(或“StackOverflow”:)用于该术语,你会发现很多关于它的好信息,以及一些不良信息。请注意,该方法还包括后置条件和类不变的概念。
让我们明确断言是一种有效的机制。
当然,它们通常在发布模式下检查(not always) ,因此这意味着您必须在发布之前测试您的代码。
如果断言被启用并且违反了断言,则某些使用断言的语言(特别是在Eiffel中)的标准行为是抛出断言违例异常。
如果您要发布代码库,那么未选中的断言不是一种方便或可行的机制,也不是(显然)验证直接可能不正确的输入的方法。如果你有“可能不正确的输入”,你必须设计作为程序正常行为的一部分,输入验证层;但你仍然可以在内部模块中自由使用断言。
其他语言,如Java,更多的传统是显式检查参数并抛出异常(如果它们是错误的),主要是因为这些语言没有强大的“断言”或“设计”按合同“传统。
(对某些人来说可能看起来很奇怪,但我发现传统上的差异是可敬的,而不一定是邪恶的。)
答案 2 :(得分:3)
您不应该使用断言来验证实时应用程序中的数据。据我所知,断言是为了测试函数是否以正确的方式使用。或者该函数返回正确的值I.e.你得到的价值是你的期望。它们在测试框架中经常使用。系统部署时,它们应该关闭,因为它们很慢。如果您想处理无效案件,您应该明确表达上述海报。
答案 3 :(得分:2)
任何可通过网络或通过进程间通信调用的代码绝对必须具有参数验证,否则它是一个安全漏洞 - 但是你必须抛出异常Debug.Assert,因为它只检查调试版本,所以不会这样做。 / p>
团队中其他人将使用的任何代码也应该有参数验证,只是因为它会帮助他们知道当他们传递无效值时他们的错误,再次你应该抛出异常因为你可以添加一个好的描述一个例外,解释他们做错了什么以及如何解决它。
你的函数中的Debug.Assert只是为了帮助你调试,这是一个很好的第一道防线,但它不是“真正的”验证。
答案 4 :(得分:2)
对于 public 函数,尤其是API调用,您应该抛出异常。消费者可能会很高兴知道他们的代码中存在错误,并且有一个例外是保证这样做的方法。
对于内部或私有函数,Debug.Assert很好(但不是必需的,IMO)。您将不会接收未知参数,并且您的测试应该按预期输出捕获任何无效值。但是,有时,Debug.Assert会让你自动进入或防止错误更快。
对于非API调用的公共函数,或其他人调用它们的内部方法,您可以采用任何一种方式。我通常更喜欢公共方法的异常,并且(通常)让内部方法没有例外。如果内部方法特别容易被滥用,则需要例外。
虽然您想要验证参数,但您不需要4级验证,您必须保持同步(并支付性能惩罚)。因此,请在外部界面进行验证,并相信您和您的同事能够适当地调用函数和/或修复不可避免的错误。
答案 5 :(得分:1)
大多数时候我不使用Debug.Assert,我会做这样的事情。
public static void Function(int i, string s)
{
if (i > 0 || !String.IsNullOrEmpty(s))
Throw New ArgumentException("blah blah");
}
警告:这是空气密码,我没有测试过。
答案 6 :(得分:1)
您应该使用Assert来验证程序化假设;也就是说,对于
的情况Assert语句允许您仔细检查是否永远不会达到不可能状态。使用此方法,无需验证即可获得舒适感。
对于函数被赋予错误参数的情况,但是您可以看到它接收这些值并不是不可能的(例如,当其他人可以调用该代码时),您应该抛出异常(la @Nathan W和@Robert Paulson)或优雅地失败(la @Srdjan Pejic)。
答案 7 :(得分:-1)
我尽量不使用Debug.Assert,而是编写警卫。如果函数参数不是预期值,我退出该函数。像这样:
public static void Function(int i, string s)
{
if(i <= 0)
{
/*exit and warn calling code */
}
}
我发现这可以减少需要发生的争吵数量。
答案 8 :(得分:-2)
我不会谈到行业标准,但您可以将最底层的两个断言合并为一行:
Debug.Assert(!String.IsNullOrEmpty(s));