【问题标题】:Refactorisation of an if Blockif 块的重构
【发布时间】:2019-01-04 13:49:14
【问题描述】:

在以下代码中,我有 2 个 if 块。
A、对象为null时第一次返回错误。
B,第二个将尝试发送对象,如果失败则返回并出错。只有不是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 来帮助我。但这对我没有帮助。

【问题讨论】:

  • 我知道这是微不足道的但我错过了一步,我不知道在哪里。
  • 所以如果一个条件为真或另一个条件为真,您想执行一些操作?
  • 好吧,我想我在 null/not null 和真值表中的 b 不正确这一事实之间迷路了。或者是星期五。

标签: c# if-statement conditional refactoring


【解决方案1】:

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

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

但是我们可以换个角度来解读这个问题。这个函数期望返回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)

代码可以使用like。

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

    var ticketIn = TicketFromFoo(foo, out error);

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

【讨论】:

  • 我认为 OP 和您回答的质量将真正受益于解释为什么您可以删除 IF...
  • @xdtTransform 我的错误。这是一个重大的忽视。我删除了我的评论
  • @MongZhu,你没有错了。 createTicketIn ticketIn; return (ticketIn = TicketFromRapport(rapport, out error))!= null && GenericAxTicketSubmit(ticketIn, out error);,但它并没有真正更具可读性或其他任何东西。我从未见过这种语法,学习起来很酷。
  • @fubo:是的,out 参数必须在SendToERP 中分配,但在TicketFromFoo 中也可以作为输出参数。因此,当一个呼叫另一个时,error = ""; 是不需要的。至少在 c#7、.net4.5 上没有。
  • @xdtTransform ,@MongZhu 我补充一下。
【解决方案2】:

我建议使用新的值元组查看 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();
    }

【讨论】:

    【解决方案3】:

    &&|| 运算符短路。它是从左到右考虑的。这意味着:

    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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-16
      • 1970-01-01
      • 2021-10-23
      相关资源
      最近更新 更多