一个简单的答案是,每当不可能执行某项操作时(由于任一应用程序或因为它可能违反业务逻辑)。如果调用了某个方法而无法执行该方法编写的操作,则抛出Exception。一个很好的例子是,如果无法使用提供的参数创建实例,则构造函数始终会引发ArgumentExceptions。另一个示例是InvalidOperationException,当由于另一个成员或类成员的状态而无法执行操作时,抛出该异常。
在您的情况下,如果调用诸如Login(用户名,密码)之类的方法,则如果用户名无效,则抛出UserNameNotValidException确实是正确的;如果密码不正确,则抛出PasswordNotCorrectException是正确的。用户无法使用提供的参数登录(即不可能,因为它会违反身份验证),因此请抛出异常。虽然我可能让您的两个Exception从ArgumentException继承。
话虽如此,如果您不希望因为登录失败很常见而抛出异常,一种策略是改为创建一种返回表示不同失败类型的方法。这是一个例子:
{ // class
...
public LoginResult Login(string user, string password)
{
if (IsInvalidUser(user))
{
return new UserInvalidLoginResult(user);
}
else if (IsInvalidPassword(user, password))
{
return new PasswordInvalidLoginResult(user, password);
}
else
{
return new SuccessfulLoginResult();
}
}
...
}
public abstract class LoginResult
{
public readonly string Message;
protected LoginResult(string message)
{
this.Message = message;
}
}
public class SuccessfulLoginResult : LoginResult
{
public SucccessfulLogin(string user)
: base(string.Format("Login for user '{0}' was successful.", user))
{ }
}
public class UserInvalidLoginResult : LoginResult
{
public UserInvalidLoginResult(string user)
: base(string.Format("The username '{0}' is invalid.", user))
{ }
}
public class PasswordInvalidLoginResult : LoginResult
{
public PasswordInvalidLoginResult(string password, string user)
: base(string.Format("The password '{0}' for username '{0}' is invalid.", password, user))
{ }
}
大多数开发人员都被教导要避免抛出异常,因为抛出异常会导致开销。意识到资源非常好,但是通常不会以牺牲应用程序设计为代价。这可能是您被告知不要抛出两个异常的原因。是否使用异常通常可以归结为异常发生的频率。如果这是一个相当普遍或相当可预期的结果,那么这是大多数开发人员会避免使用Exception,而是由于假定的资源消耗而创建另一个方法来指示失败的时候。
这是一个避免使用Try()模式在上述情况下使用异常的示例:
public class ValidatedLogin
{
public readonly string User;
public readonly string Password;
public ValidatedLogin(string user, string password)
{
if (IsInvalidUser(user))
{
throw new UserInvalidException(user);
}
else if (IsInvalidPassword(user, password))
{
throw new PasswordInvalidException(password);
}
this.User = user;
this.Password = password;
}
public static bool TryCreate(string user, string password, out ValidatedLogin validatedLogin)
{
if (IsInvalidUser(user) ||
IsInvalidPassword(user, password))
{
return false;
}
validatedLogin = new ValidatedLogin(user, password);
return true;
}
}