在没有指定案例可以处理的情况下,在switch语句中抛出异常 [英] Throwing exceptions in switch statements when no specified case can be handled
问题描述
假设我们有一个功能来更改密码用户在MVC应用程序的系统中:
public JsonResult ChangePassword
(string username,string currentPassword,string newPassword )
{
switch(this.membershipService.ValidateLogin(username,currentPassword))
{
case UserValidationResult.BasUsername:
case UserValidationResult.BadPassword:
// abort:返回JsonResult与本地化的错误消息
//无效的用户名/传递组合。
case UserValidationResult.TrialExpired
// abort:返回带有本地化错误消息的JsonResult
//用户无法登录,因为他们的试用期已过期
case UserValidationResult.Success:
休息
}
//现在修改用户验证的密码
}
membershipService.ValidateLogin()
返回一个 UserValidationResult
枚举,定义为:
枚举UserValidationResult
{
BadUsername,
BadPassword,
TrialExpired,
成功
}
作为一名防守程序员,我将更改以上 ChangePassword()
方法抛出一个异常,如果有一个无法识别的 UserValidationResult
值从 ValidateLogin()
public JsonResult ChangePassword
(string username,string currentPassword,string newPassword)
{
switch(this.membershipService.ValidateLogin(username,currentPassword))
{
case UserValidationResult.BasUsername:
case UserValidationResult.BadPassword:
// abor t:返回JsonResult与本地化的错误消息
//无效的用户名/传递组合。
case UserValidationResult.TrialExpired
// abort:返回带有本地化错误消息的JsonResult
//用户无法登录,因为他们的试用期已过期
case UserValidationResult.Success:
休息
default:
throw new NotImplementedException
(Unrecognized UserValidationResult value);
//或NotSupportedException()
break;
}
//现在修改用户验证的密码
}
我一直认为最上面的代码片段是最佳做法。例如,如果一个开发人员要求现在用户尝试登录,如果是这样的 - 或者是商业原因,他们假设先是联系业务?所以 UserValidationResult
的定义更新为:
枚举UserValidationResult
/ pre>
{
BadUsername,
BadPassword,
TrialExpired,
ContactUs,
成功
}
开发人员更改了
ValidateLogin()
方法的正文以返回新的枚举值(UserValidationResult.ContactUs
)(如果适用),但忘记更新ChangePassword()
。没有交换机的例外,用户在登录尝试甚至不能首先被验证时仍然可以更改密码!
只是我或者是这个
默认值:throw new Exception()
一个好主意?我在几年前看到,总是(在深入研究之后)认为它是一个最佳实践。解决方案我总是抛出一个在这种情况下例外。考虑使用
InvalidEnumArgumentException
,这在这种情况下提供更丰富的信息。I've been writing C# for the last 8 years and have become quite the defensive OOP programmer. Working in a statically-typed language, you do things like validate arguments in methods and throw exceptions where you wouldn't in languages that are dynamic and more liberal. I consider myself an expert in C# and am looking for feedback from other well-versed C# developers on best practices.
Let's say we have a function that changes a password for a user in a system in an MVC app.:
public JsonResult ChangePassword (string username, string currentPassword, string newPassword) { switch (this.membershipService.ValidateLogin(username, currentPassword)) { case UserValidationResult.BasUsername: case UserValidationResult.BadPassword: // abort: return JsonResult with localized error message // for invalid username/pass combo. case UserValidationResult.TrialExpired // abort: return JsonResult with localized error message // that user cannot login because their trial period has expired case UserValidationResult.Success: break; } // NOW change password now that user is validated }
membershipService.ValidateLogin()
returns aUserValidationResult
enum that is defined as:enum UserValidationResult { BadUsername, BadPassword, TrialExpired, Success }
Being a defensive programmer, I would change the above
ChangePassword()
method to throw an exception if there's an unrecognizedUserValidationResult
value back fromValidateLogin()
:public JsonResult ChangePassword (string username, string currentPassword, string newPassword) { switch (this.membershipService.ValidateLogin(username, currentPassword)) { case UserValidationResult.BasUsername: case UserValidationResult.BadPassword: // abort: return JsonResult with localized error message // for invalid username/pass combo. case UserValidationResult.TrialExpired // abort: return JsonResult with localized error message // that user cannot login because their trial period has expired case UserValidationResult.Success: break; default: throw new NotImplementedException ("Unrecognized UserValidationResult value."); // or NotSupportedException() break; } // Change password now that user is validated }
I always considered a pattern like the last snippet above a best practice. For example, what if one developer gets a requirement that now when users try to login, if for this-or-that business reason, they're suppose to contact the business first? So
UserValidationResult
's definition is updated to be:enum UserValidationResult { BadUsername, BadPassword, TrialExpired, ContactUs, Success }
The developer changes the body of the
ValidateLogin()
method to return the new enum value (UserValidationResult.ContactUs
) when applicable, but forgets to updateChangePassword()
. Without the exception in the switch, the user is still allowed to change their password when their login attempt shouldn't even be validated in the first place!Is it just me, or is this
default: throw new Exception()
a good idea? I saw it some years ago and always (after groking it) assume it to be a best practice.解决方案I always throw an exception in this case. Consider using
InvalidEnumArgumentException
, which gives richer information in this situation.这篇关于在没有指定案例可以处理的情况下,在switch语句中抛出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!