2014-08-28 71 views
1

我有以下功能,工作和循环通过3个可能的水平。 有没有办法做到以下功能相同,但不必做多个foreach语句? 基本上反应变量列表可以包含多个GroupResponseTypes 每一种可以包含多个ElementResponseBaseTypes 可以是多种类型本身 我很感兴趣,在ElementResponseType 而每ElementResponseBaseType本身找到一个值可以是GroupResponseType,它包含多种类型。C#如何避免多个foreach和if语句

所以我在看一个简单的方式,通过整个结构进行扫描特定Element.Reference 和返回相关的值

任何帮助深表感谢

public static string GetValueFromFormField(List<ResponseBaseType> responses, string fieldref) 
{ 
    string fieldvalue = String.Empty; 
    foreach (GroupResponseType groups in responses) 
    { 
     foreach (ElementResponseBaseType firstelements in groups.Responses) 
     { 
      if (firstelements.GetType() == typeof(ElementResponseType)) 
      { 
       if (firstelements.Element.Reference == fieldref) 
       { 
        ElementResponseType firstelement = new ElementResponseType(); 
        firstelement = (ElementResponseType)firstelements; 
        fieldvalue = firstelement.Value; 
       } 
      } 
      else if (firstelements.GetType() == typeof(GroupResponseType)) 
      { 
       GroupResponseType secondgroup = new GroupResponseType(); 
       secondgroup = (GroupResponseType)firstelements; 
       foreach (ElementResponseBaseType secondelements in secondgroup.Responses) 
       { 
        if (secondelements.GetType() == typeof(ElementResponseType)) 
        { 
         if (secondelements.Element.Reference == fieldref) 
         { 
          ElementResponseType secondelement = new ElementResponseType(); 
          secondelement = (ElementResponseType)secondelements; 
          fieldvalue = secondelement.Value; 
         } 
        } 
        else if (secondelements.GetType() == typeof(GroupResponseType)) 
        { 
         GroupResponseType thirdgroup = new GroupResponseType(); 
         thirdgroup = (GroupResponseType)secondelements; 
         foreach (ElementResponseBaseType thirdelements in thirdgroup.Responses) 
         { 
          if (thirdelements.GetType() == typeof(ElementResponseType)) 
          { 
           if (thirdelements.Element.Reference == fieldref) 
           { 
            ElementResponseType thirdelement = new ElementResponseType(); 
            thirdelement = (ElementResponseType)thirdelements; 
            fieldvalue = thirdelement.Value; 
           } 
          } 
         } 
        } 
       } 
      } 
     } 
    } 
    return fieldvalue; 
} 
+1

你有没有尝试使用LINQ实现更清晰的外观过滤代码? – 2014-08-28 14:25:29

+1

你不应该测试每个对象的类型并采取不同的行为,你应该使用多态。每种类型都应根据其个体差异实现一种通用方法,从而允许使用这些类型的代码进行编写,而无需知道特定对象的公共接口的哪些派生类型。 – Servy 2014-08-28 14:29:32

+0

嗨,是的,我尝试使用链接在第一个地方,但无法工作/使其迭代通过可能是n不同层次的GroupResponseType – paulmezza 2014-08-28 14:32:18

回答

0

你应该给您的基本类型,在这种情况下为ResponseBaseType,它返回它的所有decend叶节点的成员。然后,您可以针对每种类型单独实施该成员的行为。组类型可以返回所有自己孩子的所有叶子(递归),并且单个项目可以返回自己。

然后,您可以获取基本类型的任何实例并获取所有树叶,或者在此情况下获取第一片树叶。请注意,由于您只是试图在此处获得第一个结果,而不是所有这些结果,因此您可以通过使您的组成员的实现使用延迟执行而受益,因此您无需费心计算所有值只是为了获得第一。

尽管看起来很复杂,但实际上只需要很少的代码。

public abstract class ResponseBaseType 
{ 
    public abstract IEnumerable<ElementResponseType> Leaves { get; } 
} 

public class GroupResponseType : ResponseBaseType 
{ 
    public IEnumerable<ResponseBaseType> Children { get; private set; } 
    public override IEnumerable<ElementResponseType> Leaves 
    { 
     get 
     { 
      return Children.SelectMany(child => child.Leaves); 
     } 
    } 
} 

public class ElementResponseType : ResponseBaseType 
{ 
    public override IEnumerable<ElementResponseType> Leaves 
    { 
     get 
     { 
      yield return this; 
     } 
    } 
} 

这样就可以把你的回复列表中,将其映射到所有的叶子的顺序,然后得到第一/最后一片叶子。

responses.SelectMany(response => response.Leaves).Last(); 
1

您需要确定代码的哪些部分反复使用并将它们分解为新方法。如果你这样做一遍又一遍,最终你会得到这样的事情:

public static string GetValueFromResponses(IEnumerable<ElementResponseBaseType> responses, string fieldref) 
{ 
    foreach (ElementResponseBaseType response in responses) 
    { 
     ElementResponseType element = response as ElementResponseType; 
     if (element != null) 
     { 
      string foundValue = CheckElement(element, fieldref); 
      if (foundValue != null) 
      { 
       return foundValue; 
      } 
     } 
     else 
     { 
      GroupResponseType group = response as GroupResponseType; 
      if (group != null) 
      { 
       string foundValue = GetValueFromResponses(group.Responses, fieldref); 
       if (foundValue != null) 
       { 
        return foundValue; 
       } 
      } 
     } 
    } 

    return string.Empty; 
} 

private static string CheckElement(ElementResponseType element, string fieldref) 
{ 
    if (element.Element.Reference == fieldref) 
    { 
     return element.Value; 
    } 

    return null; 
} 

这是一个使用LINQ的一个版本(这包含在原始方法的所有功能):

public static string GetValueFromResponses(IEnumerable<ElementResponseBaseType> responses, string fieldref) 
{ 
    var foundInElements = responses.OfType<ElementResponseType>() 
            .Select(e => CheckElement(e, fieldref)); 
    var foundInGroups = responses.OfType<GroupResponseType>() 
           .Select(g => GetValueFromResponses(g.Responses, 
                    fieldref)); 

    return foundInElements.Concat(foundInGroups) 
          .FirstOrDefault(s => s != null) ?? string.Empty; 
} 

private static string CheckElement(ElementResponseType element, string fieldref) 
{ 
    if (element.Element.Reference == fieldref) 
    { 
     return element.Value; 
    } 

    return null; 
} 
+0

嗨,是的,这个linq版本就是我之前的版本,虽然我的起始集合是List ,但它只是最上层的版本,并且如果其中任何一个是GroupResponseType,它们都不完全一样。 ElementResponseBaseTypes。 – paulmezza 2014-08-28 14:57:00

+0

你的班级是什么? 'ElementResponseBaseType'是从ResponseBaseType继承的,还是相反? – JLRishe 2014-08-28 15:04:47