2014-08-28 110 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