1

我有一个大对象,在对它做某事之前,我需要检查多个条件。我有一个很大的功能。它是不可读的,我想把它拆开来做更小的函数,让我的代码更清晰。

该函数正在检查条件,如果有问题,它会停止并返回问题(属于一种enum类型)。

它看起来像这样:

AnswerEnum CheckEverything(Bigobj o)
{
  // some calculation 
  if (...)
   return AnswerEnum.Error1;

  // some more calculation 
  if (...)
   return AnswerEnum.Error2;

  ... 
  return AnswerEnum.OK;
}

现在,我想在较小的函数中进行计算,我可以做以下事情:

AnswerEnum CheckEverything(Bigobj o)
    { 
    AnswerEnum ret;
    ret=CheckFirstThing(o);
      if (ret!=AnswerEnum.OK)
       return ret;

    ret=CheckSecondThing(o);
      if (ret!=AnswerEnum.OK)
       return ret;

      ... 
      return AnswerEnum.OK;
    }

该解决方案包含

if (ret!=AnswerEnum.OK)
   return ret;

多次,我不喜欢它。我想尽量减少return语句的数量和代码的任何重复部分。在这种情况下我该怎么做?

4

3 回答 3

6

如果您的所有检查功能都具有相同的签名(您发布的代码中似乎就是这种情况),那么您所要做的就是创建一个委托列表,如下所示:

List<Func<Bigobj, AnswerEnum>> list;

然后在类初始化期间添加所有检查方法:

list.Add(CheckFirstThing);
list.Add(CheckSecondThing);

最后,检查一切:

AnswerEnum ret;

foreach(Func<Bigobj, AnswerEnum> f in list)
{
    ret = f(o);
    if (ret != AnswerEnum.Ok) return ret;
}
return AnswerEnum.Ok;
于 2013-10-16T11:46:25.470 回答
4

定义一个新方法:

private AnswerEnum ConditionalCheck(AnswerEnum current, 
                                    Func<BigObj, AnswerEnum> func,
                                    BigObj obj)
{
    return current == AnswerEnum.OK ? func(obj) : current;
}

然后将您的代码修改为:

AnswerEnum CheckEverything(Bigobj o)
{ 
    var ret = AnswerEnum.OK;
    ret = ConditionalCheck(ret, CheckFirstThing, o);
    ret = ConditionalCheck(ret, CheckSDecondThing, o);
    return ret;
}

或者,如果您真的想减小方法的大小,我会将其更改为:

AnswerEnum CheckEverything(List<Func<BigObj, AnswerEnum> funcs, Bigobj o)
{
    foreach (var func in funcs)
    {
        var result = func(o);
        if (result != AnswerEnum.OK) { return result; }
    }
    return AnswerEnum.OK;
}

通过这种方式,您可以注入检查集,从而使其更易于阅读、测试和维护。此外,一旦出现故障,检查就会中止,从而使其更快。

于 2013-10-16T11:49:48.863 回答
0

恕我直言,当要执行许多检查时,最好使用Delegate Dictionary Design Patternhttp://wilbloodworth.com/delegate-dictionary-pattern/ ):

AnswerEnum CheckEverything(Bigobj o)
{ 
   List<Func<AnswerEnum>> checkings = new List<Func<AnswerEnum>>
   {
     (obj)=>{return CheckFirstThing(obj);},
     (obj)=>{return CheckSecondThing(obj);}
   };

   foreach(var chk in checkings)
   {
      AnswerEnum answer;
      if((answer= chk(o))!=AnswerEnum.OK)
            return answer;
   }
   return AnswerEnum.OK;
}
于 2013-10-16T11:46:09.020 回答