LINQ-ラムダ式

「ラムダ式」という用語は、「ラムダ」計算からその名前が付けられました。これは、関数を定義するために適用される数学表記です。LINQ方程式の実行可能部分としてのラムダ式は、実行時にロジックを変換するため、データソースに簡単に渡すことができます。ただし、ラムダ式は、LINQでのみアプリケーションを見つけることに限定されていません。

これらの式は、次の構文で表されます。

(Input parameters) ⇒ Expression or statement block

これがラムダ式の例です-

y⇒y* y

上記の式はyという名前のパラメーターを指定し、yの値は2乗されます。ただし、この形式でラムダ式を実行することはできません。C#でのラムダ式の例を以下に示します。

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {

      delegate int del(int i);
      static void Main(string[] args) {

         del myDelegate = y ⇒ y * y;
         int j = myDelegate(5);
         Console.WriteLine(j);
         Console.ReadLine();
      }
   }
}

VB

Module Module1
   Private Delegate Function del(ByVal i As Integer) As Integer
   
   Sub Main(ByVal args As String())
   
      Dim myDelegate As del = Function(y) y * y
      Dim j As Integer = myDelegate(5)
      Console.WriteLine(j)
      Console.ReadLine()
	  
   End Sub
   
End Module

上記のC#またはVBのコードをコンパイルして実行すると、次の結果が得られます。

25

式ラムダ

上記のラムダ式の構文の式は右側にあるため、これらは式ラムダとも呼ばれます。

非同期ラムダ

asyncキーワードを使用して非同期処理を組み込んで作成されたラムダ式は、非同期ラムダと呼ばれます。以下は非同期ラムダの例です。

Func<Task<string>> getWordAsync = async()⇒ “hello”;

標準クエリ演算子のラムダ

クエリ演算子内のラムダ式は、要求に応じて同じものによって評価され、シーケンス全体ではなく、入力シーケンスの各要素に対して継続的に機能します。開発者は、Lambda式によって、独自のロジックを標準のクエリ演算子にフィードすることができます。以下の例では、開発者は「Where」演算子を使用して、ラムダ式を使用して、指定されたリストから奇数値を再利用しています。

C#

//Get the average of the odd Fibonacci numbers in the series... 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {     
      static void Main(string[] args) {
      
         int[] fibNum = { 1, 1, 2, 3, 5, 8, 13, 21, 34 };
         double averageValue = fibNum.Where(num ⇒ num % 2 == 1).Average();
         Console.WriteLine(averageValue);
         Console.ReadLine();
      }
   }
}

VB

Module Module1

   Sub Main()
   
      Dim fibNum As Integer() = {1, 1, 2, 3, 5, 8, 13, 21, 34}
      Dim averageValue As Double = fibNum.Where(Function(num) num Mod 2 = 1).Average()
	  
      Console.WriteLine(averageValue)
      Console.ReadLine()
	  
   End Sub
   
End Module

上記のコードをコンパイルして実行すると、次の結果が得られます。

7.33333333333333

ラムダの型推論

C#では、型推論はさまざまな状況で便利に使用され、型を明示的に指定しなくても使用できます。ただし、ラムダ式の場合、型推論は、コンパイラーが満たされる必要があるため、各型が指定されている場合にのみ機能します。次の例を考えてみましょう。

delegate int Transformer (int i);

ここで、コンパイラーは型推論を使用して、xが整数であるという事実を利用します。これは、Transformerのパラメーター型を調べることによって行われます。

ラムダ式の可変スコープ

ラムダ式内で開始される変数が外部メソッドで表示されることを意図していないように、ラムダ式で変数スコープを使用する際にはいくつかのルールがあります。キャプチャされた変数は、それを参照するデリゲートがガベージコレクションの対象にならない限り、ガベージコレクションされないという規則もあります。さらに、ラムダ式内のreturnステートメントがそれを囲むメソッドの戻りを引き起こすことを禁止するルールがあります。

ラムダ式の変数スコープを示す例を次に示します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {
      delegate bool D();
      delegate bool D2(int i);

      class Test {
         D del;
         D2 del2;
			
         public void TestMethod(int input) {
            int j = 0;
            // Initialize the delegates with lambda expressions.
            // Note access to 2 outer variables.
            // del will be invoked within this method.
            del = () ⇒ { j = 10; return j > input; };

            // del2 will be invoked after TestMethod goes out of scope.
            del2 = (x) ⇒ { return x == j; };

            // Demonstrate value of j:            
            // The delegate has not been invoked yet.
            Console.WriteLine("j = {0}", j);        // Invoke the delegate.
            bool boolResult = del();
           
            Console.WriteLine("j = {0}. b = {1}", j, boolResult);
         }

         static void Main() {
            Test test = new Test();
            test.TestMethod(5);

            // Prove that del2 still has a copy of
            // local variable j from TestMethod.
            bool result = test.del2(10);
           
            Console.WriteLine(result);

            Console.ReadKey();
         }
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が得られます。

j = 0
j = 10. b = True
True

式ツリー

ラムダ式はで使用されます Expression Tree広範囲に建設。式ツリーは、すべてのノード自体がメソッド呼び出しのような式であるか、x <yのような二項演算であるツリーに似たデータ構造のコードを提供します。以下は、式ツリーを構築するためのラムダ式の使用例です。

ステートメントラムダ

もあります statement lambdas2つまたは3つのステートメントで構成されますが、式ツリーの構築には使用されません。returnステートメントは、ステートメントlambdaで記述する必要があります。

ステートメントラムダの構文

(params)⇒ {statements}

ステートメントラムダの例

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace lambdaexample {
   class Program {
      static void Main(string[] args) {
         int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 };

         foreach (int i in source.Where(x ⇒ 
            {
               if (x <= 3)
                  return true;
               else if (x >= 7)
                  return true;
               return false;
            }
         ))
        Console.WriteLine(i);
        Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が得られます。

3
8
1
7
9
2
8

ラムダは、メソッドに基づくLINQクエリの引数として使用され、次のような演算子の左側に配置することはできません。 is または as匿名メソッドと同じように。Lambda式は匿名メソッドによく似ていますが、デリゲートとしてのみ使用するように制限されているわけではありません。

ラムダ式を使用する際の注意点

  • ラムダ式は値を返すことができ、パラメーターを持つことができます。

  • パラメータは、ラムダ式を使用して無数の方法で定義できます。

  • ラムダ式に単一のステートメントがある場合は中括弧は必要ありませんが、複数のステートメントがある場合は、中括弧と戻り値を記述する必要があります。

  • ラムダ式を使用すると、クロージャーと呼ばれる機能によってラムダ式ブロックの外部に存在する変数にアクセスできます。クロージャーの使用は、問題を回避するために慎重に行う必要があります。

  • ラムダ式内で安全でないコードを実行することは不可能です。

  • ラムダ式は、オペレーターの左側で使用するためのものではありません。