如果在Lambda函数中声明?

时间:2009-06-03 13:48:12

标签: c# .net c#-3.0 lambda

这可能很简单,但我对Lambda很新,所以请耐心等待。

我有一个使用Lambda函数递归的函数。 主函数收到一个bool,告诉它在lambda中包含某些信息。

该函数旨在将自定义类写出为XML - 我认为代码非常自我解释。

目前我已经使用一个简单的if语句克服了这个问题,但感觉很丑,所以想知道是否有人知道更好的方法?

        private XElement ErrorListToXml(ErrorList el, bool outputTagsOnly)
    {
        // Need to declare in advance to call within the lambda.
        Func<ErrorType, XElement> recursiveGenerator = null;

        if (outputTagsOnly)
            recursiveGenerator = error => new XElement
                (error.Name,
                 error.ChildErrors.Select(recursiveGenerator));
        else
            recursiveGenerator = error => new XElement
          (error.Name,
          new XAttribute("Ignore", error.Filter),
           error.ChildErrors.Select(recursiveGenerator));


        var element = new XElement
                   ("ErrorList",
                    ChildErrors.Select(recursiveGenerator));

        Console.WriteLine(element);

        return element;
    }

5 个答案:

答案 0 :(得分:6)

如果您愿意,可以安全地在lambda函数中移动“if”语句:

Func<ErrorType, XElement> recursiveGenerator = null;

recursiveGenerator = (error =>
    outputTagsOnly
        ? new XElement(error.Name,
                       error.ChildErrors.Select(recursiveGenerator));
        : new XElement(error.Name, new XAttribute("Ignore", error.Filter),
                       error.ChildErrors.Select(recursiveGenerator)));

var element = new XElement("ErrorList", ChildErrors.Select(recursiveGenerator));

除此之外,似乎没有任何简单的方法来简化你所拥有的。

(P.S。当它看起来很丑的时候,通过漂亮的印刷在猪身上涂一些口红;)

答案 1 :(得分:6)

您可以很容易地在lambda中的相同类型的值之间做出决定:

customer => flag ? customer.Name : customer.Address

您可以在lambda中使用if语句,但需要更多努力:

customer =>
{
  if (flag)
    return customer.Name
  else
    return customer.Address
}

这些都不会对你的方法有很大帮助。

答案 2 :(得分:6)

可以略微改进mquander的解决方案,以减少重复。您可以使用以下事实:您可以在XElement构造函数内容中传入null元素,并将其忽略。因此,我们可以进一步推动这一条件:

Func<ErrorType, XElement> recursiveGenerator = null;    
recursiveGenerator = (error => new XElement(error.Name,
            outputTagsOnly ? null : new XAttribute("Ignore", error.Filter),
            error.ChildErrors.Select(recursiveGenerator));

var element = new XElement("ErrorList", ChildErrors.Select(recursiveGenerator));

答案 3 :(得分:0)

我想你可以做到这一点,但是结束了它仍然是一个if:

                recursiveGenerator = error => outputTagsOnly ? 
                   new XElement(error.Name,error.ChildErrors.Select(recursiveGenerator)
              : 
              new XElement(error.Name,new XAttribute("Ignore", error.Filter), 
             error.ChildErrors.Select(recursiveGenerator);

答案 4 :(得分:0)

您可以尝试将问题分解为两个不同的问题:

  1. 如何根据错误结构构建树。
  2. 将什么放入树节点。
  3. 然后代码看起来像:

            private XElement ErrorListToXml(ErrorList el, bool outputTagsOnly)
            {
                // Need to declare in advance to call within the lambda.
                Func<ErrorType, XElement> treeGenerator = null;
                Func<ErrorType, object[]> elementParametersGenerator = null;
    
                treeGenerator = error => new XElement
                    (error.Name,
                    elementParametersGenerator(error));
    
                if(outputTagsOnly)
                    elementParametersGenerator = error => 
                        new object[] {error.ChildErrors.Select(treeGenerator)};
                else
                    elementParametersGenerator = error => 
                        new object[] { new XAttribute("Ignore", error.Filter), error.ChildErrors.Select(treeGenerator) };
    
                var element = new XElement
                           ("ErrorList",
                            ChildErrors.Select(treeGenerator));
    
                Console.WriteLine(element);
    
                return element;
            }
    

    在这种特殊情况下没有明显改善,但这是一种更通用的方法。