在返回之前测试错误和清理的正确方法

时间:2012-10-01 12:40:03

标签: c coding-style error-handling return

以下两种实施方式中,以编码风格:更好,为什么?

UINT Fn1()
{
    HKEY hRegKey;

    if(RegOpenKeyEx(..., KEY_NAME, &hRegKey) != ERROR_SUCCESS)
        return ERROR_KEY_OPEN;
    if(RegQueryValueEx(hRegKey, VAL_A_NAME, ...) != ERROR_SUCCESS)
    {
        RegCloseKey(hRegKey);
        return ERROR_KEYVAL_A;
    }

    if(RegQueryValueEx(hRegKey, VAL_B_NAME, ...) != ERROR_SUCCESS)
    {
        RegCloseKey(hRegKey);
        return ERROR_KEYVAL_B;
    }

    RegCloseKey(hRegKey);
    return ERROR_SUCCESS;
}

UINT Fn2()
{
    UINT rVal;
    HKEY hRegKey;

    if(RegOpenKeyEx(..., KEY_NAME, &hRegKey) == ERROR_SUCCESS)
    {
        if(RegQueryValueEx(hRegKey, VALUE_A_NAME, ...) == ERROR_SUCCESS)
        {
            if(RegQueryValueEx(hRegKey, VALUE_B_NAME, ...) == ERROR_SUCCESS)
                rVal = ERROR_SUCCESS;
            else
                rVal = ERROR_KEYVAL_B;
        }
        else
            rVal = ERROR_KEYVAL_A;
        RegCloseKey(hRegKey);
    }
    else
        rVal = ERROR_KEY_OPEN;

    return rVal;
}

另外,还有更好的方法吗?
注意:请不要混淆代码段的细节 - 强调代码流和样式。

1 个答案:

答案 0 :(得分:1)

这非常属于个人品味。我个人说,看起来既不好看也不容易。 C中我个人更喜欢的形式是:

int
fn(void)
{
    struct foo *foo;
    int error = 0;
    if ((foo = foo_open(...)) == NULL)
        return FOO_ERROR_OPEN;
    if (foo_do_something(1)) {
        error = FOO_ERROR_1;
        goto out;
    }
    if (foo_do_something(2)) {
        error = FOO_ERROR_2;
    }
out:
    foo_close(foo);
    return error;
}

但正如所说,这是一个品味问题,并且有很多人对此有意见,因为有程序员。我更喜欢这种风格,因为这就是我职业生涯早期编写的许多代码的编写方式,这些代码对我来说是最具可读性的。

如果我必须选择你提出的一种风格,我会选择1,因为2因为深度缩进而看起来很乱。我的经验法则是可读性随压痕深度而减小。