纠正功能的正确方法

时间:2013-10-16 11:38:17

标签: c# function

我有一个大对象,在我用它做某事之前,我需要检查多个条件。我有一个很大的功能。这是不可读的,我想把它拆分为较小的功能,使我的代码更清晰。

该函数正在检查条件,如果某些内容不正确,它会停止并返回问题(属于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语句的数量和代码的任何重复部分。在这种情况下我该怎么做?

3 个答案:

答案 0 :(得分: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;

答案 1 :(得分: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;
}

这样您就可以注入一组检查,因此更容易阅读,测试和维护。此外,一旦出现故障就检查中止,使其更快。

答案 2 :(得分: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;
}