2009-06-03 78 views
4

這可能很簡單,但我對Lambda的新東西很感興趣。如果語句在Lambda函數內?

我有一個使用lambda函數遞歸函數。 主函數收到一個布爾值,告訴它在lambda中包含或不包含某些信息。

該功能的目的是寫出一個自定義類爲XML - 我認爲的代碼是非常強的自我explanitory。

在我已經克服了使用簡單的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; 
    } 

回答

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

您可以移動「如果」拉姆達函數內部聲明安全,如果首選:

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

除此之外,似乎沒有被簡化了任何微不足道的方式,你有了。

(PS當它看起來難看,穿上了那頭豬的漂亮,在打印一些口紅;)

+0

感謝這也正是我一直在尋找 – Chris 2009-06-03 13:56:48

+0

這裏的表現比原來的代碼略差:您檢查標誌outputTagsOnly上一代_every_節點,而這是完全不必要的,你可以檢查一次。 (當然,對於小的輸入數據來說,它是微不足道的) – 2009-06-03 14:16:21

+1

是的,我意識到這一點,但是與實際構建XML元素的開銷相比,標誌檢查是微不足道的,我認爲它與可讀性相比絕對不爲重要。 – mquander 2009-06-03 14:18:33

0

我想你可以做到這一點,但是這一天結束它仍然是一個如果:

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

可以使同一類型的值之間的決定拉姆達很容易地:

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

您可以在拉姆達使用if語句,再努力一點:

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

這些都不利於你的方法極大。

0

你可以嘗試分解你的問題分爲兩個不同的:

  1. 如何建立從錯誤中結構的樹。
  2. 什麼投入樹節點。

然後代碼將看起來像:

 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; 
     } 

沒有任何在這種特殊情況下顯著更好,但它是一個更通用的方法。