質問

Microsoft Lambda Expression のドキュメントをすばやく読みました。

この種の例は、理解を深めるのに役立ちましたが、

delegate int del(int i);
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25

それでも、なぜそれがそのような革新なのか理解できません。これは、<!> quot; method variable <!> quot;終わりますよね?実際の方法の代わりにこれを使用する必要があるのはなぜですか?

役に立ちましたか?

解決

ラムダ式は匿名デリゲート用のより単純な構文であり、匿名デリゲートを使用できるすべての場所で使用できます。ただし、その逆は当てはまりません。ラムダ式は、LINQ to SQLのような多くの魔法を可能にする式ツリーに変換できます。

以下は、 LINQ to Objects 式の使用例です。匿名デリゲートは、ラムダ式を使用して、目で見てどれだけ簡単かを示します。

// anonymous delegate
var evens = Enumerable
                .Range(1, 100)
                .Where(delegate(int x) { return (x % 2) == 0; })
                .ToList();

// lambda expression
var evens = Enumerable
                .Range(1, 100)
                .Where(x => (x % 2) == 0)
                .ToList();

ラムダ式と匿名デリゲートは、個別の関数を書くよりも利点があります:クロージャー パラメータを追加せずに関数にローカル状態を渡すことができます関数または1回限りのオブジェクトの作成。

式ツリーは非常に強力な新機能ですAPIが実行可能なメソッドへの参照を取得する代わりに、式の構造を参照できるようにするC#3.0 APIは、デリゲートパラメータを Expression&lt; T&gt; パラメータにするだけで、コンパイラは匿名デリゲートではなくラムダから式ツリーを生成します。

void Example(Predicate<int> aDelegate);

次のように呼ばれます:

Example(x => x > 5);

なる:

void Example(Expression<Predicate<int>> expressionTree);

後者には、式を記述する抽象構文ツリーの表現が渡されます> x&gt; 5 。 LINQ to SQLは、この動作に依存して、サーバー側でのフィルタリング/順序付けなどに必要なSQL式にC#式を変換できるようにします。

他のヒント

匿名関数と式は、完全なメソッドを作成するために必要な余分な作業の恩恵を受けない1回限りのメソッドに役立ちます。

この例を検討してください:

 string person = people.Find(person => person.Contains("Joe"));

 public string FindPerson(string nameContains, List<string> persons)
 {
     foreach (string person in persons)
         if (person.Contains(nameContains))
             return person;
     return null;
 }

これらは機能的に同等です。

別のコントロールを使用して、あるコントロールのイベントのハンドラーを宣言したい場合に便利です。 通常、これを行うには、作成されたものとは異なるメソッドでコントロールを使用できるように、クラスのフィールドにコントロールの参照を保存する必要があります。

private ComboBox combo;
private Label label;

public CreateControls()
{
    combo = new ComboBox();
    label = new Label();
    //some initializing code
    combo.SelectedIndexChanged += new EventHandler(combo_SelectedIndexChanged);
}

void combo_SelectedIndexChanged(object sender, EventArgs e)
{
    label.Text = combo.SelectedValue;
}

ラムダ式のおかげで、次のように使用できます:

public CreateControls()
{
    ComboBox combo = new ComboBox();
    Label label = new Label();
    //some initializing code
    combo.SelectedIndexChanged += (s, e) => {label.Text = combo.SelectedValue;};
}

はるかに簡単。

LambdaはC#2.0の匿名デリゲート構文をクリーンアップしました...たとえば

Strings.Find(s => s == "hello");

次のようにC#2.0で行われました:

Strings.Find(delegate(String s) { return s == "hello"; });

機能的には、まったく同じことを行いますが、構文ははるかに簡潔です。

これは、ラムダ式を使用する1つの方法にすぎません。デリゲートを使用できるラムダ式どこでもを使用できます。これにより、次のようなことができます。

List<string> strings = new List<string>();
strings.Add("Good");
strings.Add("Morning")
strings.Add("Starshine");
strings.Add("The");
strings.Add("Earth");
strings.Add("says");
strings.Add("hello");

strings.Find(s => s == "hello");

このコードは、単語「こんにちは」に一致するエントリをリストから検索します。これを行うもう1つの方法は、次のように、実際にFindメソッドにデリゲートを渡すことです。

List<string> strings = new List<string>();
strings.Add("Good");
strings.Add("Morning")
strings.Add("Starshine");
strings.Add("The");
strings.Add("Earth");
strings.Add("says");
strings.Add("hello");

private static bool FindHello(String s)
{
    return s == "hello";
}

strings.Find(FindHello);

編集

C#2.0では、匿名デリゲート構文を使用してこれを実行できます。

  strings.Find(delegate(String s) { return s == "hello"; });

Lambdaはその構文を大幅にクリーンアップしました。

Microsoftは、Lambda式と呼ばれる匿名デリゲートを作成する、よりクリーンで便利な方法を提供してくれました。ただし、このステートメントの expressions 部分にはあまり注意が払われていません。 Microsoftは、 System.Linq.Expressions という名前空間全体をリリースしました。 、ラムダ式に基づいて式ツリーを作成するクラスが含まれています。式ツリーは、ロジックを表すオブジェクトで構成されています。たとえば、x = y + zは、.Netの式ツリーの一部になる可能性がある式です。次の(単純な)例について考えてみましょう:

using System;
using System.Linq;
using System.Linq.Expressions;


namespace ExpressionTreeThingy
{
    class Program
    {
        static void Main(string[] args)
        {
            Expression<Func<int, int>> expr = (x) => x + 1; //this is not a delegate, but an object
            var del = expr.Compile(); //compiles the object to a CLR delegate, at runtime
            Console.WriteLine(del(5)); //we are just invoking a delegate at this point
            Console.ReadKey();
        }
    }
}

この例は簡単です。 「実行時に式を作成してコンパイルするのではなく、デリゲートを直接作成できたので、これは役に立たない」と考えていると確信しています。そして、あなたは正しいでしょう。しかし、これは式ツリーの基礎を提供します。 Expressions名前空間には多くの式が用意されており、独自の式を作成できます。これは、設計時またはコンパイル時にアルゴリズムがどうあるべきかを正確に知らない場合に役立つことがわかると思います。これを使用して関数電卓を作成する例を見ました。 Bayesian システム、または遺伝的プログラミング(AI)。私のキャリアの中で、利用可能なデータを操作するためにユーザーが簡単な式(追加、サブトラクションなど)を入力できるExcelのような機能を書く必要がありました。 .Net 3.5より前では、C#の外部のスクリプト言語に頼るか、リフレクションでコード生成機能を使用して.Netコードをオンザフライで作成する必要がありました。ここで、式ツリーを使用します。

特定の場所で1回だけ使用されるメソッドを使用する必要がないため、使用される場所から遠く離れた場所で定義されます。ソートなどの汎用アルゴリズムのコンパレーターとして使用すると便利です。ソートを実行するカスタムソート関数を定義すると、ソート対象を確認するために他の場所を探す必要がなくなります。

そして、それは本当にイノベーションではありません。 LISPには約30年以上にわたってラムダ関数があります。

ラムダ式は、デリゲートインスタンスの代わりに記述された匿名メソッドのようなものです。

delegate int MyDelagate (int i);
MyDelagate delSquareFunction = x => x * x;

ラムダ式を考慮 x =&gt; x * x;

  

入力パラメーター値はx(= gt;の左側)

     

関数のロジックはx * x(= gt;の右側)

ラムダ式のコードは、式ではなくステートメントブロックにすることができます。

x => {return x * x;};

注: Func は定義済みの汎用デリゲートです。

    Console.WriteLine(MyMethod(x => "Hi " + x));

    public static string MyMethod(Func<string, string> strategy)
    {
        return strategy("Lijo").ToString();
    }

参照

  1. デリゲート&amp;インターフェースは互換的に使用されますか?

メソッドに作用する汎用コードを記述する際にラムダ式を使用することもできます。

例:メソッド呼び出しにかかった時間を計算する汎用関数。 (つまり、ここの Action

public static long Measure(Action action)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    action();
    sw.Stop();
    return sw.ElapsedMilliseconds;
}

そして、次のようにラムダ式を使用して上記のメソッドを呼び出すことができます

var timeTaken = Measure(() => yourMethod(param));

式を使用すると、メソッドから戻り値を取得し、paramも出力できます

var timeTaken = Measure(() => returnValue = yourMethod(param, out outParam));

多くの場合、機能は1か所でしか使用しないため、メソッドを作成するとクラスが煩雑になります。

ラムダ式は、匿名メソッドを表す簡潔な方法です。無名メソッドとLambda式の両方で、メソッド実装をインラインで定義できますが、匿名メソッドでは、メソッドのパラメータータイプと戻り値タイプを明示的に定義する必要があります。 Lambda式は、コンパイラがコンテキストに基づいて変数の型を推測できるようにするC#3.0の型推論機能を使用します。それは非常に便利です。なぜなら、それは私たちに多くの入力を節約するからです!

これは、小さな操作を行い、それを使用場所に非常に近づける方法です(変数をその使用ポイントの近くで宣言するのと同じです)。これにより、コードが読みやすくなります。式を匿名化することで、関数が他の場所で使用され、「enhance」に変更された場合、誰かがクライアントコードを解読することを非常に難しくしています。それ。

同様に、なぜforeachを使用する必要があるのですか? foreachのすべてを、プレーンなforループを使用するか、IEnumerableを直接使用するだけで実行できます。回答:あなたはそれを必要しませんが、それはあなたのコードをより読みやすくします。

革新的なのは、型の安全性と透明性です。ラムダ式の型は宣言しませんが、推論されており、コード検索、静的分析、リファクタリングツール、およびランタイムリフレクションで使用できます。

たとえば、SQLを使用してSQLインジェクション攻撃を受ける可能性がある前に、ハッカーが通常数字が予想される文字列を渡したためです。ここで、LINQラムダ式を使用しますが、これは保護されています。

純粋なデリゲートでLINQ APIを構築することはできません。評価する前に式ツリーを結合する必要があるためです。

2016年、ほとんどの一般的な言語はラムダ式をサポートしており、C#は主流の命令型言語の中でこの進化の先駆者。

これは、おそらくラムダ式を使用する理由に関する最良の説明です-&gt; https://youtu.be/j9nj5dTo54Q

要約すると、コードの読みやすさを改善し、コードを複製するのではなく再利用することでエラーの可能性を減らし、舞台裏で発生する最適化を活用することです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top