C#如何避免多个foreach和if语句

时间:2014-08-28 14:23:06

标签: c# .net

我有以下功能可以工作并循环3个可能的级别。 有没有办法像下面的函数一样,但不必执行多个foreach语句? 基本上,响应列表可以包含多个GroupResponseTypes 每个都可以包含多个ElementResponseBaseTypes 它本身可以是各种类型 我有兴趣在ElementResponseType中找到一个值 并且每个ElementResponseBaseType本身可以是GroupResponseType,它包含多个类型。

因此,我正在寻找一种简单的方法来扫描整个结构中的特定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;
}

2 个答案:

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

答案 1 :(得分:0)

您应该为您的基类型(在本例中为ResponseBaseType)提供一个返回其所有死代叶节点的成员。然后,您可以为每种类型单独实现该成员的行为。组类型可以返回其所有子节点中的所有叶子(递归地),并且单个项目可以返回自身。

然后,您可以获取基类型的任何实例并获取所有叶子,或者在本例中为第一个叶子。请注意,由于您只是尝试获取第一个结果,而不是所有结果,因此您可以从使组成员的实现使用延迟执行中受益,这样您就不需要费心计算所有值只是为了得到第一个。

起初看起来很复杂,实际实现的代码很少。

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();