2013-07-21 27 views
8

我在C#中工作,所以我已经在C#下发布了这个,尽管这可能是一个可以用任何编程语言回答的问题。返回有意义的返回值的方法

有时我会创建一个方法来做一些事情,例如将用户登录到网站。通常情况下,我从方法返回一个布尔值,但是这经常会导致问题,因为布尔返回值没有传达任何上下文。如果在登录用户时发生错误,我无法知道导致错误的原因。

这里是我目前使用的方法的例子,但想改变,因此它返回的不仅仅是0或1

public bool LoginToTwitter(String username, String password) 
{ 
    // Some code to log the user in 
} 

上述方法更只能返回真或假。这个效果很好,因为我可以调用如下。

if(http.LoginToTwitter(username, password)) 
{ 
    // Logged in 
} else { 
    // Not Logged in 
} 

但问题是我不知道为什么在没有登录用户的方式有很多原因可能存在,如:错误的用户名/密码组合,暂停帐户,帐户需要用户注意等。但使用以下方法和逻辑,不可能知道这一点。

我有什么替代方法?

回答

8

您可以使用预期的LoginResults创建并返回enum

public enum LoginResult 
{ 
    Success, 
    AccountSuspended, 
    WrongUsername, 
    WrongPassword, 
} 

然后返回你的方法用枚举类型:

public LoginResult LoginToTwitter(String username, String password) 
{ 
    // Some code to log the user in 
} 
+0

发生新的错误情况时发生了什么。 @丹? – xhamr

+0

@jvra如果有任何意外的例外,我相信他们应该重新抛出,因为一些其他的答案表明。但是,您的代码应该能够处理所有预期的情况:错误的用户名,错误的密码,帐户暂停等等,并将这些预期情况返回给您的应用程序处理的枚举。 –

+0

但事实是,当你想处理其他错误枚举。你的代码会随着你的常量枚举的增长而增长。但如果你知道将来你不可能有更多的常量枚举,那么这是可以接受的。 – xhamr

8

你可以选择是抛出附有相关信息的异常(并有调用的方法处理除外),或该函数返回具有不同状态的enum(如LoginState.SuccessLoginState.IncorrectPassword等)。

如果您使用的例外,它可能是最好的让你的函数返回什么(public void LoginToTwitter),但如果您使用的是enum,确保设定的返回类型的名称,您enumpublic LoginState LoginToTwitter)。

6

有两种标准方式。如果您只对结果感兴趣,但不感兴趣,请返回一些枚举。将可用值设置为Success,Suspended等(所有可能的结果)

如果您需要更多详细信息,则可以始终使用例外情况。基本上按照“告诉,不要问”的想法,并写一个你的函数的方式,它返回所需的值(例如用户ID?或者可能没有,如果你有一些全局登录状态)只有在成功和抛出一个异常详细否则描述失败。关于层次结构本身,你应该最有可能实现一个LoginException与一些更具体的子类,并只捕获那些。 (它可以很容易地验证所有相关的异常处理,并将所有未知的异常处理到更高级别)

3

两个返回一个枚举或抛出一个异常,在其他的答案建议,是合理的。但我的首选是返回异常。听起来很疯狂,但它可以让你的调用者决定是否使用错误检查或异常处理。而且,与枚举不同的是,异常是分层的,因此处理整个类别的失败变得更加容易,并且可以携带任意额外的数据。

我觉得Sayse有一个类似的想法,但他删除了他的答案,从来没有真正解释过它。

+0

所以基本上,'null'就意味着*成功* - 这看起来相当违反直觉。当然,如果你真的需要一个返回值,比如(说)用户信息......我可以用Smalltalk这种动态类型的语言看到它的一个很好的例子,但是像C#这样的静态类型语言使得这种麻烦。 – cHao

+0

@cHao:如果进一步处理需要返回一些其他信息,则抛出异常开始变得更有意义。但是,如果登录失败是预期的结果......以及我不会在非特殊情况下使用“throw”。 –

+0

我半惊讶没有人认为是一个'LoginResult'类型,它不是一个例外,但也不仅仅是一个枚举。它会提供返回任意信息的灵活性,而不会诱使人们抛出非例外条件的例外情况。 – cHao

0

您可以使用c中经常使用的习语。赋值表达式的结果是表达式本身 - 这意味着你可以在同一时间捕捉的结果代码为评估它是否是一个特定的值:

if ((status = DoSomething()) == AnErrorEnum.NotAnError) 
{//success handler 
} 
else 
{//failure handler 
} 

我被要求提供一个链接到一个MSDN文章 - 这里是旧版本的规范: http://msdn.microsoft.com/en-us/library/aa691315(v=vs.71).aspx

“简单赋值表达式的结果是分配给左操作数的值,结果与左操作数的类型相同,并且始终归类为值。 “

+0

这很有趣。请链接到MSDN文档? –

+0

这是在规格,它是可供下载:这是2003年旧规格的部分:http://msdn.microsoft.com/en-us/library/aa691315(v=vs.71).aspx –