MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
C Sharpの基礎 - ラムダ式のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
C Sharpの基礎 - ラムダ式
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == ラムダ式とは、関数(メソッド)を整数等の変数と全く同列に扱う手法のことである。<br> <br> * デリゲートに対して代入すると、匿名メソッドと同じ扱いになる。<br>ラムダ式は、匿名メソッドと比較して、より簡潔に記述することができる。 * Expression型の変数に代入すると、式木データになる。 <br><br> == ラムダ式 == ==== 匿名関数 ==== ラムダ式の特徴を以下に示す。<br> * 匿名関数を使用することにより、インラインでデリゲートの定義を記述し、デリゲートを作成できる。 * 匿名関数の1つにラムダ式がある。 * 匿名関数の1つである匿名メソッドよりも簡潔に記述することができる。 * C# 3.0以降であれば、ラムダ式を使用すべきである。 <br> コンパイラは、匿名関数の記述に該当するクラスメソッドまたはインスタンスメソッドにおいて、必要であれば新たにクラスを生成する。<br> 匿名関数によるデリゲートは、コンパイラが生成したメソッドを参照するデリゲートとして作成される。<br> <br> デリゲートの作成において、C# 3.0で追加されたラムダ式を使用することで、匿名メソッドよりも簡潔に記述できる。<br> また、IEnumerable<T>を実装したクラスであればインスタンスメソッドとして記述できる。<br> <br> <syntaxhighlight lang="csharp"> // 匿名メソッド Func<string, bool> predicate = delegate (string str) { return str.Length < 5; }; // ラムダ式 Func<string, bool> predicate = (string str) => { return str.Length < 5; }; // ラムダ式を更に短く記述 Func<string, bool> predicate = str => str.Length < 5; </syntaxhighlight> <br> ==== Action ==== Actionは、パラメータを受け取り、戻り値を返さないデリゲート (メソッドを参照する型) である。<Br> 戻り値がない (voidを返す) メソッドを表現する場合に使用する。<br> <br> 引数は0〜16個までのパラメータを受け取ることが可能である。<br> コンソール出力やデータの保存等の処理に使用されることが多い。<br> <br> マルチスレッドでGUIを処理する場合にも、invokeメソッドと同時に使用することがある。<br> 詳細は、[[C_Sharpの基礎_-_マルチスレッドとGUI#Invokeメソッドを使う]]を参照すること。<br> <br> <syntaxhighlight lang="c#"> // Actionの基本 Action sayHello = () => Console.WriteLine("Hello, Action"); sayHello(); // 出力: Hello, Action // 引数が1つのAction Action<string> greet = (name) => Console.WriteLine($"Hello, {name}!"); greet("John"); // 出力: Hello, John! // 引数を2つのAction Action<int, int> printSum = (x, y) => Console.WriteLine($"Sum: {x + y}"); printSum(5, 3); // 出力: Sum: 8 // コレクション処理 (リストの各要素を2倍にする) List<int> numbers = new List<int> { 1, 2, 3, 4, 5 }; Action<int> twiceNumber = (n) => Console.WriteLine($"Number: {n * 2}"); numbers.ForEach(twiceNumber); // イベントハンドリング Action<string> logMessage = (message) => Console.WriteLine($"Log: {message}"); // メソッドの引数にする void ProcessItems<T>(IEnumerable<T> items, Action<T> processor) { foreach (var item in items) { processor(item); } } </syntaxhighlight> <br> また、Actionを使用してラムダ式の即時実行を行うこともできる。<br> <syntaxhighlight lang="c#"> // 括弧を使用した即時実行 new Action<int>(x => { x++; })(1); // Invokeメソッドを使用した即時実行 new Action<int>(x => { x++; }).Invoke(1); // ローカル変数を使用・変更する場合 int result = 1; new Action<int>(x => { result = x + 1; Console.WriteLine($"値 : {result}"); })(1); </syntaxhighlight> <br> ==== Func ==== Funcとは、パラメータを受け取り、値を返すデリゲートである。<br> 最後の型パラメータが戻り値の型を表す。<br> <br> 0〜16個までの入力パラメータを受け取ることができる。<br> <br> Funcは、値の変換や計算処理によく使用されている。<br> <br> <syntaxhighlight lang="c#"> // Funcの基本 Func<int> getRandomNumber = () => new Random().Next(1, 100); int random = getRandomNumber(); // 1〜100までのランダムな数値を取得 // 引数を1つ受け取り、戻り値を返すFunc Func<int, bool> isEven = (number) => number % 2 == 0; bool result = isEven(4); // true // 引数が2つでdouble型の戻り値を返すFunc Func<int, int, double> calculateAverage = (x, y) => (x + y) / 2.0; double average = calculateAverage(10, 15); // 12.5 // コレクション処理 (リストの要素を変換) List<int> numbers = new List<int> { 1, 2, 3, 4, 5 }; Func<int, string> numberToString = (n) => $"Value: {n}"; List<string> stringNumbers = numbers.Select(numberToString).ToList(); // 条件付き処理 Func<int, string> gradeScore = (score) => { if (score >= 90) return "A"; if (score >= 80) return "B"; if (score >= 70) return "C"; if (score >= 60) return "D"; return "F"; }; int studentScore = 85; string grade = gradeScore(studentScore); // "B" // 引数にFuncを渡す public static T TransformData<T>(string input, Func<string, T> transformer) { return transformer(input); } </syntaxhighlight> <br> ==== コレクション処理 ==== <syntaxhighlight lang="csharp"> var names = new List<string> { "Taro", "Jiro", "Saburo" }; int count = CountList(names, str => str.Length < 5); </syntaxhighlight> <br> ==== LINQとの連携 ==== LINQの各メソッドと組み合わせることにより、効率的なコレクション処理が可能である。<br> <br> 以下の例では、LINQのCountメソッドを記述している。<br> <br> 拡張メソッドであるCountメソッドは、IEnumerable<T>型の拡張メソッドであり、引数はFunc<TSource, bool>型である。<br> また、Countメソッドは、nullチェック等の処理も含まれている。<br> <syntaxhighlight lang="csharp"> int count = names.Count(str => str.Length < 5); </syntaxhighlight> <br> また、拡張メソッドと型推論を知ることで、LINQをより理解することができる。<br> LINQの詳細は、[[LINQ - 拡張メソッド一覧|C_Sharpの基礎 - LINQ]]を参照すること。<br> <br> ==== 式木データ ==== ラムダ式は、式木データとして扱うこともできる。<br> <br> <code>Pred p = n => n > 0;</code>のように、デリゲートに代入する場合は、ラムダ式は匿名メソッドと同じ扱いとなる。<br> これに対して、ラムダ式を<code>Expression</code>型の変数に代入すると、式木データとして扱うことができ、<br> 以下のように、式中の項を取得するといった操作ができる。<br> <syntaxhighlight lang="csharp"> Expression<Func<int, bool>> e = n => n > 0; BinaryExpression lt = (BinaryExpression)e.Body; ParameterExpression en = (ParameterExpression)lt.Left; ConstantExpression zero = (ConstantExpression)lt.Right; </syntaxhighlight> <br> インタプリタ型の関数型言語には、匿名関数と式木データを区別しないものがあり、ある時はラムダ式を匿名関数として、またある時は式木データとして使用することができる。<br> C#では、デリゲートまたはExpression型によりコンパイル結果を変更することで、関数型言語と似たような動作を実現している。<br> <br> ただし、ラムダ式をデリゲートに代入する場合と違い、式木データには制約がある。<br> <u>式木データに代入できるものは、単文の({}を使用しない)ラムダ式だけである。</u><br> したがって、四則演算やメソッドコールは式木データにできるが、forやwhile等の制御構文は式木データにできない。<br> (Expression型には、forやwhile等に相当するノードはない)<br> <br> 以下の例では、1つ目のラムダ式はコンパイル可能であるが、2つ目はコンパイルエラーになる。<br> <syntaxhighlight lang="csharp"> // コンパイル可能 Expression<Func<int, bool>> p = n => n > 0; // コンパイルエラー Expression<Func<int, int, int>> f = (x, y) => { int sum = x + y; int prod = x * y; return sum * prod; }; </syntaxhighlight> <br> また、LINQ to SQLでは、ラムダ式の式木データを使用して、LINQクエリ式の条件式等を式木データとして取得し、<br> それをSQLクエリに変換して、データベースに問い合わせをかける。<br> <br> 例えば、以下のようなLINQクエリ式の場合、db.Whereやdb.Selectでは、<br> データベースサーバに対して以下のようなSQLを発行する仕組みになっている。<br> <br> これは、<code>c.City == "London"</code>の部分を式木データとして取得して、その内容を見ながらSQL文を生成している。<br> <syntaxhighlight lang="csharp"> // LINQクエリ式 var q = from c in db where c.City == "London" select new {c.City}; foreach (var city in q) { // do something } // 等価のSQL文 SELECT TOP 1 [t0].[City] FROM [Customers] AS [t0] WHERE [t0].[City] = @p0 </syntaxhighlight> <br><br> == デフォルト引数 == C# 12以降、ラムダ式の引数に既定値を与えることができる。<br> <syntaxhighlight lang="c#"> // 既定値の指定 var fn = (int x = 10) => 1; </syntaxhighlight> <br> また、params引数も使用することができる。<br> <syntaxhighlight lang="c#"> // params引数 var fn = (params int[] y) => 1; </syntaxhighlight> <br> 既定値とparams引数も同時に使用することができる。<br> <syntaxhighlight lang="c#"> var fn = (int x = 1, params int[] y) => 1; </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:C_Sharp]]
C Sharpの基礎 - ラムダ式
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse