C# 对Validate()方法抛出异常是一种好的做法,还是返回bool值更好?

C# 对Validate()方法抛出异常是一种好的做法,还是返回bool值更好?,c#,java,exception,validation,C#,Java,Exception,Validation,是否建议从验证方法中抛出异常,如: ValidateDates(); ValidateCargoDetails(); 除此之外:是否经常使用稳健的验证设计模式?我通常使用访客模式来验证输入;将所有错误累积到一个列表或其他内容中,以显示给用户。逻辑是这样的,检查验证错误列表,如果发现,通知用户,否则很好 在我看来,验证错误并非例外,因此不应像处理错误一样处理。我建议返回包含ValidationFailures的ValidationResult对象。 您不应该将异常用作逻辑编码的一部分。异常是针对

是否建议从验证方法中抛出异常,如:

ValidateDates();
ValidateCargoDetails();

除此之外:是否经常使用稳健的验证设计模式?

我通常使用
访客模式
来验证输入;将所有错误累积到一个列表或其他内容中,以显示给用户。逻辑是这样的,检查验证错误列表,如果发现,通知用户,否则很好


在我看来,验证错误并非例外,因此不应像处理错误一样处理。

我建议返回包含ValidationFailures的ValidationResult对象。
您不应该将异常用作逻辑编码的一部分。异常是针对异常的

引发异常必须用于控制应用程序流。顾名思义,它发生在异常情况下,而验证通常会失败。它们也非常昂贵,影响性能


我会选择返回一个布尔值加上一个字符串,原因是

很多情况取决于异常验证失败的程度以及纠正的关键程度

如果您的验证失败非常罕见、严重或致命,我会使用异常甚至断言错误。大多数解析器使用异常,这些异常表示无法继续处理


如果您的验证失败与正常操作一样,并不表示您无法继续处理,我建议使用访客模式或返回问题列表(可以为空)

我认为这完全取决于您执行验证的方式。但是在一天结束时,开发人员总是可以选择忽略返回的结果(这是他们的问题),他们不能在不编写明确代码的情况下忽略异常。

用户输入无效数据就是异常的定义。在为解决方案编写业务需求时,您总是将非错误路径作为主流,将错误路径作为异常路径。使用异常进行验证是完全可以接受的。使用异常验证还允许您按处理顺序排列优先级,并根据您在体系结构堆栈中所处的级别不同地处理错误(描述错误的字符串在数据访问层几乎没有用处)。

老实说,我对所有这一切都持谨慎态度。有时我也在构建访问者模式,但它确实感觉我只是在重新实现异常

我绝对不喜欢访客模式的一点是,如果你的六个级别都很深,并且你注意到你需要中断,你必须检查上面每个级别的结果

这意味着很多样板代码实际上会引入bug

示例 如果您选中了
A
,它不会验证,但代码会继续检查
B
,这实际上取决于正确初始化的
A
?在复杂的验证逻辑中,这可能发生在许多不同的路径上。它容易出错

另一方面,我使用(定制)
ValidationExceptions
,没有遇到任何重大问题。您点击了一些未验证的内容,并确保跳过所有其他验证逻辑。这是代码简单性的一大胜利

“抛出异常不能用于控制应用程序的流程。”-对于99%的其他情况,我会同意,但在我看来,坚持这一点进行验证逻辑似乎是基于教条,而不是实用主义

关于绩效: 性能方面的原因99%与用户输入的验证逻辑无关,因为这几乎从来都不是在紧密循环中完成的


总结:我建议忽略“异常适用于异常事物”的教条,创建(自定义!)在顶层抛出并捕获的异常,看看它是否适用于您。对我来说确实如此。

我只是想把这一点带到图片中,Radzberg在博客上的回答:

简言之,我们不需要限制自己使用布尔作为返回类型

我并不是说我们应该使用或不使用异常

但是对于那篇特定的文章——你在一开始就构建了糟糕的代码,然后试图让它变得更好。从一开始就构建好代码,并解释为什么使用异常会更好。 这是我的例子

class TooManyLoginAttempts extends ValidationError{}

if ($hasTooManyLoginAttempts) {
    return new TooManyLoginAttempts()
}
...
$validationResult = $this->validate();
if ($validationResult instanceof ValidationError) {
    $this->errorLogger->log($validationResult->getMessage());
}
它还解决了所有描述的问题
–无幻数
–我们正在解决在整个应用程序中存在错误代码的问题
–我的代码要短得多,并且遵循开闭原则


我来自:哪个被锁定。

验证失败不应该是异常的吗?@Peter Lawrey-根据我的经验,用户输入无效数据是规则,而不是异常。@Jarrett,我认为这很大程度上取决于您正在验证什么以及您需要对失败采取什么措施。异常对用户没有用处,他们希望对他们应该做的事情进行友好的描述。但是,如果需要停止处理,异常是有用的,可以忽略的友好消息是危险的。@PeterLawrey:在决定某个内容是否应该是异常时,最好的问题是“是否需要立即调用代码来处理该条件?”如果不是,则抛出异常。代码调用验证例程这一事实非常强烈地表明,代码已经准备好处理失败的可能性。这并不是100%的暗示——调用者除了异常失败之外可能不准备做任何事情,但可能调用了例程以避免执行稍后会失败的操作——但它更倾向于使用错误返回码而不是异常。我真的不知道这条规则是从何而来的。如果操作失败,