C# 如何验证参数;“高起”;在调用堆栈上完成了吗?

C# 如何验证参数;“高起”;在调用堆栈上完成了吗?,c#,parameter-passing,callstack,C#,Parameter Passing,Callstack,我一直在阅读《框架设计指南》一书,这是一本关于在.NET中设计框架的书,其中摘录了框架设计师关于每个部分的决策(例如参数设计、异常处理等) 在参数设计下,其中一个技巧是尽可能地验证“调用堆栈上的高级别”的参数。这是因为这里的工作没有调用堆栈中较低的工作那么昂贵,所以在调用堆栈中较高的位置进行验证时,性能损失也没有那么昂贵 这是否意味着当我将参数传递到方法或构造函数中时,我会在执行任何其他操作之前对其进行验证,还是在使用参数之前进行验证(这样定义中的参数和参数的使用之间可能有100行代码) 谢谢快

我一直在阅读《框架设计指南》一书,这是一本关于在.NET中设计框架的书,其中摘录了框架设计师关于每个部分的决策(例如参数设计、异常处理等)

在参数设计下,其中一个技巧是尽可能地验证“调用堆栈上的高级别”的参数。这是因为这里的工作没有调用堆栈中较低的工作那么昂贵,所以在调用堆栈中较高的位置进行验证时,性能损失也没有那么昂贵

这是否意味着当我将参数传递到方法或构造函数中时,我会在执行任何其他操作之前对其进行验证,还是在使用参数之前进行验证(这样定义中的参数和参数的使用之间可能有100行代码)


谢谢

快速失败通常是一种很好的做法。传递给方法的所有参数都应该尽快进行验证,之前不会执行任何不必要的计算,因为这样可以简化调试并允许更容易地从错误情况中恢复


关于输入验证,我认为性能是一个次要的问题。

< P>我没有阅读您提到的具体指南,但我希望他们讨论的是方法>代码> A<代码>调用方法>代码> b>代码>,调用方法>代码> c>代码>,参数值通过所有三个调用。在方法<代码> > A/<代码>的开始时,最好在方法>代码> C <代码>的某个地方验证该参数,因为如果它无效,则跳过所有发生在<代码> > <代码> > <代码> b>代码>和<代码> c>代码>的所有事件。如果在循环内调用
B
C
,则情况尤其如此,因为低级别验证将多次发生,而不是在
A
开始时仅发生一次


当然,您必须平衡这一点和参数验证的复杂性。如果您在使用它的同一位置验证它,可能会更容易理解。

尽早在您的方法中验证它们

我认为这意味着,您应该在收到可能无效的数据后立即对其进行验证。一旦验证,则无需再进行检查。如果您一直等到调用堆栈的底部,那么您可能需要多次验证,因为您的调用树可能有许多分支

我完全同意这一建议,但不是以业绩为理由。通过在入口点进行验证,您可以更好地向提供数据的客户机提供有意义的错误消息。通过减少验证的数量,您将得到更清晰的代码

  • 更喜欢在程序集的公共API中进行验证。这意味着公共类的公共方法

  • 更喜欢在类的公共方法中进行验证。因此,如果您的类需要一个指向另一个对象的非空指针才能正常工作,您可以通过要求它作为构造函数参数并在提供空指针时引发异常来强制执行该操作。从那时起,所有成员方法都不需要测试指针是否为非null


  • 其思想是没有用户可以通过提供无效数据来破坏类(或程序集)。当然,这两种方式代码都不会工作,但是如果您以可控的方式失败,那么调用代码就更清楚什么是错误的,并且不会产生令人不快的副作用,比如资源泄漏(或更糟)

    我相信你的第一个结论是正确的,在最后一个可能的情况下验证它,在这种情况下,值可能会以对性能产生不利影响或导致问题的方式更改。是的,你是正确的,即先验证然后执行代码(阅读合同设计模式)。好处非常简单。例外情况是昂贵的,尤其是当它们在层中冒泡时。因此,首先验证参数,然后执行代码是一种很好的做法。这是在传入参数之后还是在使用参数之前?作为补充说明,如果您是调用和调用代码的作者,我认为早期失败(允许抛出空ptr异常等)而不是显式验证就足够了。无论哪种方式,都应该失败或尽早验证。