2013-05-09 49 views
9

下面是一些代碼,(顯然)不會編譯:在Linq查詢中執行代碼塊的語法?

var q = from x in myAnonymousTypeCollection 
     select new { 
      x.ID, 
      CalcField = { 
         switch(x.SomeField) { 
          case 1: 
          return Math.Sqrt(x.Field1); 
          case 2: 
          return Math.Pow(x.Field2, 2); 
          default: 
          return x.Field3; 
         } 
         } 
     }; 

你得到的圖片;我試圖以完全不同的方式計算CalcField,具體取決於SomeField的值。我不能使用Func<>(或者我能嗎?),因爲輸入類型是匿名的。那麼讓這個工作起來的正確語法是什麼?

+0

這是Linq的對象? – cadrell0 2013-05-09 16:40:15

+1

使用lambda或匿名函數。 – 2013-05-09 16:40:43

+0

@ofstream - 我知道我可以使用lambda來做,但出於在我的實際代碼中可讀性的原因,我想使用查詢語法。 – 2013-05-09 16:42:17

回答

9

首先,我通常更喜歡LINQ查詢語法的方法鏈語法。有了這個,你可以輕鬆做到這一點。

var q = myAnonymousTypeCollection 
    .Select(x => 
      { 
       object calcField; 

       switch(x.SomeField) 
       { 
         case 1: 
         calcField = Math.Sqrt(x.Field1); 
         case 2: 
         calcField = Math.Pow(x.Field2, 2); 
         default: 
         calcField = x.Field3; 

       return new 
         { 
          x.ID, 
          CalcField = calcField 
         }; 
      }); 

不使用方法鏈,你需要或者方法或函數功能。我們假設一個Func

//replace these with actual types if you can. 
Func<dynamic, dynamic> calculateField = 
    x => 
    { 
     switch(x.SomeField) { 
      case 1: 
       return Math.Sqrt(x.Field1); 
      case 2: 
       return Math.Pow(x.Field2, 2); 
      default: 
       return x.Field3; 
    } 

var q = from x in myAnonymousTypeCollection 
     select new { x.Id, CalcField = calculateField(x) }; 

注意:我沒有在IDE中寫這個,所以請原諒任何簡單的錯誤。

這是dynamic的MSDN。但是,我發現一旦你需要開始傳遞匿名類型,最好是創建一個實際的類。

+0

+1哦,偷偷摸摸,用'動態'!儘管如此,我更喜歡強類型,到目前爲止,我正在使用第一個選項(lambda語法)。等待有效的查詢語法(如果存在),然後再給予答案信貸。 :-) – 2013-05-09 16:54:34

7

您可以將您的匿名函數作爲(自行執行)Func<>委託包裝。這假定你知道返回類型。

var q = from x in myAnonymousTypeCollection 
    select new { 
     ID = x.ID, 
     CalcField = new Func<double>(() => { 
        switch(x.SomeField) { 
         case 1: 
         return Math.Sqrt(x.Field1); 
         case 2: 
         return Math.Pow(x.Field2, 2); 
         default: 
         return x.Field3; 
        } 
        })() 
    }; 
+0

+1:很好!這個概念與JavaScript類似:執行匿名函數:'(function(){...})();' – 2013-05-09 16:48:17

+0

請注意,在這種情況下,從可讀性/維護角度來看,一個命名的函數,你只需在LINQ查詢中調用,即使這會起作用。 – Servy 2013-05-09 16:49:03

+0

+1非常好。如果返回類型也是匿名的呢? :-) – 2013-05-09 17:08:59

0

你可以很容易地進行移動切換邏輯到另一個函數,像這樣:

private static T GetReturnValue<T>(myClass x) 
{ 
    switch (x) 
    { 
     case 1: 
      return Math.Sqrt(x.Field1); 
      break; 
     case 2: 
      return Math.Pow(x.Field2, 
          2); 
      break; 
     default: 
      return x.Field3; 
      break; 
    } 
} 

然後你只需要你的對象傳遞給該功能找回你想要的值:

var q = from x in myAnonymousTypeCollection 
        select new 
         { 
          ID = x.ID, 
          CalcField = GetReturnValue(x) 
         }; 
+0

當然,如果我有一個定義的類型,就像你一樣('myClass'),這很容易。但我使用的是匿名類型... – 2013-05-09 16:57:13