if 块的重构

Refactorisation of an if Block

在下面的代码中,我有 2 个 if 块。
A、第一个return对象为null时的错误
B,第二个将尝试发送对象,如果失败则 return 和错误。只有非A才执行,对象不为null。

private bool SendToERP(Foo foo, out string error)
{
    error = "";
    var ticketIn = TicketFromFoo(foo, out string err);

    if(ticketIn == null)
    {
        error = err;
        return false;
    }

    if ( !GenericERP_TicketSubmit(ticketIn, out err))
    {
        error = err;
        return false;
    }

    return true;
}

这些条件相同后的操作,我想重构为一个独特的 if 块。

因为我无法扭曲我的头 2 条件和一个 and 我写了一个 simple truth table 来帮助我。但这并没有帮助我。

&&||运算符短路。它被认为是从左到右。这意味着:

1) 如果 && 将其第一个操作数评估为假,则不会评估其第二个操作数。

2) 如果 || 评估其第一个操作数为真,则不会评估其第二个操作数。

在您的情况下,如果 ticketIn 为空,则您不希望执行 TicketSubmit。 因此,您可以通过 OR 对 2 个条件进行分组。像这样。

    var ticketIn = TicketFromFoo(foo, out string err);        
    if(ticketIn == null || !GenericERP_TicketSubmit(ticketIn, out err))
    {
         error = err;
         return false;
    }
    return true;

在您的问题中,您可以将两个 IF 合并为 @Thierry V 的答案

if(ticketIn == null || !GenericERP_TicketSubmit(ticketIn, out err))

但是我们可以换个角度来读题。这个函数期望 return bool 所以我们只能写在语句中而不是 IF.

return !(ticketIn == null || !GenericERP_TicketSubmit(ticketIn, out err))

我们可以用另一个技巧(De Morgan's laws)让!进入语句,即 将所有逻辑反转,让代码更清晰

1.ticketIn == null 将是 ticketIn != null

2.|| 将是 &&

3.!GenericERP_TicketSubmit(ticketIn, out err) 将是 GenericERP_TicketSubmit(ticketIn, out err)

所以我们可以得到

return ticketIn != null && GenericERP_TicketSubmit(ticketIn, out err)

代码可以像这样使用。

private bool SendToERP(Foo foo, out string error)
{
    error = "";

    var ticketIn = TicketFromFoo(foo, out error);

    return ticketIn != null && GenericERP_TicketSubmit(ticketIn, out error);
}

我建议查看带有新值元组的 c# 7。我们也可以用这种方式重构所有代码:

    private (bool result, string error) SendToERP(Foo foo)
    {
        var result = TryMakeTicketFromFoo(foo, out TicketIn ticketIn);
        return result.isSuccess ? GenericERP_TicketSubmit(ticketIn) : result;
    }

您还需要重构其他方法的语义:

    private (bool isSuccess, string error) GenericERP_TicketSubmit(TicketIn ticketIn)
    {
        throw new NotImplementedException();
    }

    private (bool isSuccess, string error) TryMakeTicketFromFoo(Foo foo, out TicketIn ticketIn)
    {
        throw new NotImplementedException();
    }