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();
}
在下面的代码中,我有 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();
}