检查参考参数值还是返回布尔值?

Posted

技术标签:

【中文标题】检查参考参数值还是返回布尔值?【英文标题】:Check reference parameter value or return bool? 【发布时间】:2011-04-06 21:20:32 【问题描述】:

我正在使用具有以下签名的方法:

public static bool TryAuthenticate(string userName, string password, 
    string domainName, out AuthenticationFailure authenticationFailure)

该方法声明:bool authenticated = false; 然后继续对用户进行身份验证。

每当authenticated 设置为true 或false,authenticationFailure 就会相应地设置为AuthenticationFailure.FailureAuthenticationFailure.Success

所以基本上我可以使用 authenticationFailure 或方法的返回值来检查结果。然而,在同一方法中使用这两种方法似乎是对 DRY 的毫无意义的违反。

澄清一下,authenticationFailure 没有在该方法的其他任何地方使用,因此它看起来完全是多余的。

目前我正在这样做:

public static bool IsValidLDAPUser(string username, string password, string domain)

    var authenticationStatus = new AuthenticationFailure();   
    if (ActiveDirectoryAuthenticationService.TryAuthenticate(username, password, domain, out authenticationStatus)) 
        return true;
    else return false;

但我可以这样做并得到一个相似的结果:

public static AuthenticationFailure IsValidLDAPUser(string username, string password, string domain)

    var authenticationStatus = new AuthenticationFailure();   
    ActiveDirectoryAuthenticationService.TryAuthenticate(username, password, domain, out authenticationStatus)
    return authenticationStatus;

为什么会有一个与返回值做同样事情的引用参数? 我应该使用哪一个来检查结果,它有什么不同吗? 这只是代码错误还是我没有抓住重点?

提前致谢!

【问题讨论】:

我认为您的第二个代码块可能包含错误。返回类型不应该是bool 而不是AuthenticationFailure 还是应该将return 语句更改为返回authenticationStatus 【参考方案1】:

恕我直言,我不认为这是 bool vs ref 的事情。对我来说,似乎在参考中返回了错误的东西。

我希望看到以下方法

public static bool TryAuthenticate(string userName, 
               string password, 
               string domainName, 
               out User user)

public static User Authenticate(string userName, 
               string password,                    
               string domainName)

一种用于您不关心原因的情况,另一种用于您关心的情况。例如

这允许调用代码进行身份验证,然后在没有捕获的情况下执行某些操作

User u;
if (TryAuthenticate(user,pass,domain,ref u))
  //do somthing
else
  return;

或者,如果他们需要额外的信息,那么使用 catch

例如

User u;
try

    u = Authenticate(user,pass,domain);
    //do somthing

catch(AuthenticationError ae)

    switch (ae.Failure)
    
        case AuthenticationFailure.AccountLocked:
            //dosomthing A
            break;
        case AuthenticationFailure.BadPassword:
            //dosomthing B
            break;
        case AuthenticationFailure.InvalidUser:
            //dosomthing c
            break;
        etc..

    

现在如果没有用户或令牌的概念,那么可能不需要 Try Pattern

【讨论】:

【参考方案2】:

与返回值相比,Ref 参数不太容易使用和理解。但是,在某些情况下,使用 ref 参数可能是有利的。对于这种情况,如果我们假设分配 AuthenticationFailure 是耗时的,那么使用 ref 参数是合适的,因为在认证成功的情况下不需要分配。

无论如何,在这种情况下,我更喜欢使用 AuthenticationResult 返回类型,因为应该不会影响性能。

【讨论】:

【参考方案3】:

首先,您的枚举变量名称对我来说似乎有点扭曲。 AuthenticationFailure.Success 没有多大意义!应该是AuthenticationResult 之类的。此外,由于在您的方法中您只关心身份验证是否成功,因此您应该返回 bool。你在想 DRY 但也想 KISS!

您仍然可以将枚举用于您可能添加的其他错误代码,但是查看方法的返回值应该会告诉您它是否成功。如果您希望找到失败原因的详细信息,请使用作为“out”参数传递的枚举。

【讨论】:

是的,我注意到枚举的命名并没有经过深思熟虑。幸运的是,这段代码不是我编写的,我也不维护它——它是公司范围内巨大的通用库之一。【参考方案4】:

通常有更多的错误代码,而不仅仅是成功或失败。也许这种方法的设计者会为所有不同的故障类型添加更多的枚举。

有时,也有不止一种成功类型——例如。 HTTP 在 200 和 300 块中有很多返回码,它们在某种程度上都被认为是成功的。因此,布尔值通常会告诉您它是否成功,而枚举会提供更准确的信息。

有很多方法可以做到这一点,这一种是不寻常的,但如果他们计划添加更多代码,则不反对 DRY。

另一种方法是封装到具有枚举和IsSuccess 属性的Result 类中。您甚至可以提供到 bool 的转换,以便在 if 语句中使用。

【讨论】:

好点 - 我刚刚看了一下 TryAuthenticate 的可扩展性,结果发现 AuthenticationFailure 有各种其他值,如 AccountDisabled、PasswordExpired、InvalidWorkstation 等等......所以我将继续检查布尔值,但当身份验证失败时可能会使用 AuthenticationFailure 来提供一些关于失败原因的反馈。【参考方案5】:

如果函数只返回一个值,则应优先使用常规函数返回值,而不是 outref 参数。

我想说这对于名为 IsXyz 的方法(重点是 is)更为重要,并且以这种方式命名的方法应该返回 bool

【讨论】:

以上是关于检查参考参数值还是返回布尔值?的主要内容,如果未能解决你的问题,请参考以下文章

检查两个值是不是存在并返回命名布尔值

如何检查布尔值是真还是假?

php 代码数组布尔值返回

Python:如何检查列表是不是包含数值并返回布尔值?

检查数据库中是不是存在行,并返回布尔值

检查整数是不是为 0 并返回布尔值的简短方法