检查方法是否返回false:将结果分配给临时变量,还是直接将方法调用置于条件中?


9

调用在if语句中返回true或false值的方法是一种好习惯吗?

像这样:

private void VerifyAccount()
{
    if (!ValidateCredentials(txtUser.Text, txtPassword.Text))
    {
        MessageBox.Show("Invalid user name or password");
    }
}

private bool ValidateCredentials(string userName, string password)
{
    string existingPassword = GetUserPassword(userName);
    if (existingPassword == null)
        return false;

    var hasher = new Hasher { SaltSize = 16 };
    bool passwordsMatch = hasher.CompareStringToHash(password, existingPassword);

    return passwordsMatch;
}

还是将它们存储在变量中,然后使用if这样的其他值比较它们是否更好?

bool validate = ValidateCredentials(txtUser.Text, txtPassword.Text);
if(validate == false){
    //Do something
}

我不仅指.NET,还指所有编程语言中的问题,恰巧我以.NET为例。


3
如果您确实使用了临时变量,请写if (!validate)而不是if (validate == false)
菲利普(Philip)

12
我会将该函数命名为“ CredentialsAreValid()”,因此您应该知道该函数应返回布尔值,否则,它是一个好习惯
Zachary K

3
IsValidCredentials尽管语法上很笨拙,但它是一种用于表示布尔返回值的通用格式。
zzzzBov 2012年

@Philip if(!validate)和这个if(validate)之间有什么区别?
KyelJdD 2012年

!是“ NOT”运算符,它会否定任何布尔表达式。所以if (!validate)是相反的if (validate)。如果validate不正确,将输入if语句。
菲利普(Philip)

Answers:


26

与所有这些事情一样,这取决于。

如果您不打算使用调用的结果,ValidateCredentials则不需要(除了出于调试目的)将结果存储在本地变量中。但是,如果它使代码更具可读性(并因此更易于维护),则可以使用变量。

代码不会明显降低效率。


1
是可读的吗?就像我在上面所做的一样
KyelJmD 2012年

@KyelJmD:这取决于您正在编程的文化。在我编程过的地方,!ValidateCredentials它更具可读性,因为它明确说明了代码中的工作。很清楚 如果您要调用的函数没有“自我记录”名称,则最好使用该变量。就目前而言,我建议您省略该变量,并保留您拥有的自我记录代码。
乔尔·埃瑟顿

首先,ValidateCredentials不可读-名称如何告诉您结果的含义?CredentialsAreValid或CredentialsAreInvalid都好得多。
gnasher729

9

为什么要使用其他变量?我更喜欢使用第一种方法,它更具可读性和简单性。


4

调用在if语句中返回true或false值的方法是一种好习惯吗?

是的,如果条件不够简单以内联并使其可读。

还是将它们存储在变量中,然后使用if这样的其他值比较它们是否更好?

仅当您在多个位置使用该值或需要该值以使代码更具可读性时,才应该这样做。否则,无需分配变量。不必要的代码充其量是浪费,最坏的情况是缺陷的根源。


2

让我们看看...

因为一切都是关于KISS的,所以没有它时就无需创建其他变量。此外,无需输入更多...。

但是然后由于您DRY,如果您稍后要调用ValidateCredentials并发现自己在打字ValidateCredentials(txtUser.Text, txtPassword.Text),则知道您应该创建了一个附加变量。


2

是的,通常可以使用类似条件的方法。如果方法名称指示该方法返回布尔值,则将很有帮助。例如CanValidateCredentials。在C风格的语言中,此方法通常采用Is和Can前缀的形式,而在Ruby中则带有“?” 后缀。


1
关于方法名称的要点,但我永远不会以“ if”开头方法名称。然后代码显示为“ if if”。“能”是确定的:if (cat.canOpenCanOfCatFood())
凯文·克莱恩

谢谢,@ Kevin。我的意思是“不是”。我编辑了答案
Christian Horsdal 2012年

1

尚未指出的另一个问题是:短路评估。这两个代码片段之间有什么区别?

示例#1:

if(foo() && bar() && baz())
{
    quz();
}

例#2:

bool isFoo = foo();
bool isBar = bar();
bool isBaz = baz();
if(isFoo && isBar && isBaz)
{
    quz();
}

这两个代码片段似乎做相同的事情,但是如果您的语言支持短路评估,那么这两个片段是不同的。短路评估意味着代码将评估通过或失败条件所需的最低要求。如果是示例1,则foo()返回false时,甚至不会评估bar()和baz()。如果baz()是长时间运行的函数调用,这将很有用,因为如果foo()返回false或foo()返回true且bar()返回false,则可以跳过它。

示例2中不是这种情况。foo(),bar()和baz()总是被评估。如果期望bar()和baz()表现出副作用,则示例1会出现问题。上面的示例1实际上与此等效:

例#3:

if(foo())
{
    if(bar())
    {
        if(baz())
        {
            quz();
        }
    }
}

在示例#1和#2之间进行选择时,请注意代码中的这些差异。


1

扩展一些可读性问题...

我可以想到将结果存储在变量中的两个很好的理由:

  1. 如果要多次使用该条件,则将其保存在变量中意味着您只需调用该函数一次。(这假定存储的值仍然有效;如果您需要重新测试它,那么这当然不适用。)

  2. 如果将其存储在变量中,则通过为条件赋予一个比您在函数调用中看到的名称更有意义的名称来提高可读性。

例如,这:

bool foo_is_ok = is_ok(foo);
if (foo_is_ok) ...

不利于可读性,但这是:

bool done_processing = feof(file1) && feof(file2);
if (done_processing) ...

可能feof(file1) && feof(file2)会这样做,因为目前尚不很明显,这意味着我们已经完成了处理。

问题中的passwordsMatch变量可能是比我的更好的例子。

如果一次性变量为某个值赋予有意义的名称,则它们将很有用。(这当然是为了人类读者的利益。)


我想,我宁愿发表评论而不是引入done_processing变量。毕竟,名称done_processing具有注释功能。真正的评论使我可以说一两个字,说明为什么这种情况表明我们已经完成处理。不过,并不是说我是个很棒的评论者,我可能都不用真实的代码做任何事……
cmaster-恢复莫妮卡2015年

@cmaster:注释的一个问题是它们很容易与代码不同步。名为变量的变量done_processing是表达意图的更持久的方式。
基思·汤普森

点号2的+1-有时一个好名字的temp var确实可以使事情变得清晰。
user949300
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.