最佳实践返回值与例外与Enum的比较

Jan*_*Jan 13 c# enums login exception

我试图找出具有多个结果值的方法的优点和缺点.

例如,我正在使用登录方法.如果登录成功,它将通过,否则我需要知道它失败的原因.

1.返回真或假(信息不足)

bool Login(string user, string password);
Run Code Online (Sandbox Code Playgroud)

2.如果成功则返回true,否则抛出异常

public class UnknownUserException : Exception { }
public class WrongPasswordException : Exception { }
bool Login(string user, string password);
Run Code Online (Sandbox Code Playgroud)

什么也没有.如果不成功则抛出异常

public class UnknownUserException : Exception { }
public class WrongPasswordException : Exception { }
void Login(string user, string password);
Run Code Online (Sandbox Code Playgroud)

4.返回枚举值

enum LoginResult
{
    Successful
    UnknownUser,
    WrongPassword
}
LoginResult Login(string user, string password);
Run Code Online (Sandbox Code Playgroud)

"登录"只是一个示例.我想知道不同实现的优点和缺点是什么,在哪些情况下它们或多或少是合适的.

Dav*_*vid 5

绝对不是例外。登录失败几乎不是“例外”情况,它只是应用程序的正常逻辑过程。如果您使用异常,那么除了处理登录失败的情况外,您将始终必须使用异常处理程序包装登录。这似乎是对逻辑流使用异常的定义,这是不对的。

如果您需要返回特定信息(登录功能并不总是需要这些信息,但可能是您的情况),#4 似乎是合理的。你可以更进一步,让它成为一个对象:

public class LoginResult
{
    // an enum for the status
    // a string for a more specific message
    // a valid user object on successful login
    // etc.
}
Run Code Online (Sandbox Code Playgroud)

或者,根据它的逻辑,一个不可变的结构而不是一个类。(确保结构是不可变的,可变结构只是自找麻烦。)重点是您可以在结果对象本身上应用各种逻辑和功能,这似乎是您前进的方向。


Sri*_*vel 4

你会得到更多固执己见的答案,如果我这样做,我会结合 3 和 4。抛出LoginFailedException一个枚举来说明原因。

void Login(string user, string password);//Or return a bool(redundant though)

class LoginFailedException : ApplicationException
{
    public LoginFailReason Reason {get; private set;}
    public LoginFailedException(LoginFailReason reason)
    {
       this.Reason = reason;
    }
}

enum LoginFailReason
{
    UnknownUser,
    WrongPassword
}
Run Code Online (Sandbox Code Playgroud)

选择例外选项的原因:假设您选择仅返回值方法,您的 api 的用户(可能是客户端或其他开发人员)可能有机会忽略该 API。

instance.Login(user, password);
var accountInfo = instance.GetAccountInfo();//Assuming logged in; going to explode
Run Code Online (Sandbox Code Playgroud)

谁知道他们必须这样做

if(instance.Login(user, password) == LoginResult.Successful))
{
    var accountInfo = instance.GetAccountInfo();
}
Run Code Online (Sandbox Code Playgroud)

因此,IMO 抛出异常,说由于某某原因,我无法处理您的登录请求。让它变得简单。

  • 我喜欢这种方法,尽管在看起来很常见的场景中抛出异常感觉是错误的。我觉得异常应该用在“特殊”场景中,即在更深层次上出现问题的情况。 (6认同)
  • @Moeri我相信这是正确的方法,登录失败不是常见情况,而是一种**例外**情况,考虑到您只选择枚举方法,并且您开发了一个公共API,如果用户不这样做怎么办检查返回值并仅调用“Login();”并假设已登录。?把它扔到脸上说嘿,出了点问题(与 sqlserver 通过 SqlException 所做的一样) (4认同)