2013-05-09 5 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; 
         } 
         } 
     }; 

あなたが画像を取得します。私はSomeFieldの値が何であるかによって、全く異なる方法でCalcFieldを計算しようとしています。 Func<>は使用できません(または入力できますか?)。入力タイプが匿名であるためです。これを機能させるには正しい構文は何でしょうか?

+0

このLinq to Objectsですか? – cadrell0

+1

ラムダ関数または匿名関数を使用します。 –

+0

@ofstream - 私はラムダを使ってそれを行うことができますが、実際のコードでは読みやすくするために、クエリ構文を使いたいと思います。 –

答えて

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が必要です。 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構文)を使用しています。クレジットを返す前に、有効なクエリ構文(存在する場合)を待っています。 :-) –

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(){)})();' –

+0

このような状況では、可読性/保守の観点から、これが機能するとしても、単にLINQクエリを呼び出す名前付き関数です。 – Servy

+0

+1とてもいいです。戻り値の型も匿名の場合はどうなりますか? :-) –

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')のように定義された型を持っていれば、それは簡単でしょう。しかし、私は匿名のタイプを使用しています... –