7

StudentプロパティIdNameおよびを持つという名前のクラスがありPhoneます。UI フォームにはStudent、次のようなリストがあります。

List<Student> students=new List<Student>();

最後にdataGridview_Cellclick、以下のコードが使用されるイベントのコードがあります。

string id = dataGridview.Rows[e.RownIndex].Cells[0].Value.ToString();  
Student aStudent = students.Find(i=> i.Id== id);

は何をしstudents.Find(i=> i.Id== id)ますか?どういう意味ですか?=>サインの意味は何ですか?それはどのように機能しますか?

4

6 に答える 6

4

それらはラムダ式と呼ばれます...ラムダ式は特別な構文を使用します。関数を変数やフィールドなどのデータとして使用できます。ラムダ式の構文は => 演算子を使用します。これにより、無名関数のパラメーターとステートメント本体が分離されます。

これは「Goes to」と言い換えることができます。

=> 演算子は「goes to」と読むことができ、ラムダ式を宣言するときに常に使用されます。ラムダ式を使用すると、実行可能なステートメントを含む関数をパラメーター、変数、またはフィールドとして使用できます。

MSDN のこのリンクを参照 して、理解を深めてください。

于 2012-12-01T09:25:17.843 に答える
3

これは、入力変数をラムダ本体から分離するためにラムダ式(匿名メソッドの作成)で使用されるgoes to演算子 (またはラムダ演算子) です。

サンプルのstudents.Find(i => i.Id== id)入力変数でiは、ラムダ本体に移動しますi.Id == id(つまり、匿名メソッドのパラメーターとして渡されます)。


また、使用している onList<T>.Findメソッドも参照してください。タイプの述語を受け入れTますが、あなたの場合は になりますPredicate<Student>。Predicated はデリゲートであり、一連の基準を定義し、指定されたオブジェクトがそれらの基準を満たすかどうかを判断するメソッドを表します。次の署名があります。

public delegate bool Predicate<in Student>(Student obj)

したがって、学生オブジェクトを受け入れて bool を返すメソッドを渡す必要があります。これには、通常の名前付きメソッドを作成できます。

private bool IsStudentHasIdEqualTo5(Student s)
{
   return s.Id == 5;
}

そして、このように使用します:

Student aStudent = students.Find(IsStudentHasIdEqualTo5);

ただし、異なる id 値を確認する必要があります。2 つのオプションがあります - クラスにフィールドを作成するか、このメソッドとフィールドの両方を持つクラスを作成します。

class StudentSearcher
{
    private int _id; // capture id

    public StudentSearcher(int id)
    {
        _id = id;
    }

    // method has same signature as bool Predicate(Student obj)
    public bool VerfyId(Student s)
    {
        return s.Id == _id;
    }
}

idこの名前付きメソッドを使用して、学生の検証にさまざまな値を指定できるようになりました。

var searcher = new StudentSearcher(id);
Student aStudent = students.Find(searcher.VerfyId);

しかし、検索ごとにそのようなメソッドやクラスを作成するのはあまり効率的ではありません。これが、デリゲート (およびラムダ) がある理由です。新しい名前付きメソッドを宣言する代わりに、必要な場所に正確に名前なし (匿名) のメソッドを作成でき、コンパイラは通常の名前付きメソッドを生成します。

Student aStudent = students.Find(delegate(Student s) { 
                                      return s.Id == id; 
                                 });

まったく同じコードをラムダ構文で記述できます (delegate キーワードを省略し、パラメーターの型を推測し、goes toパラメーターとメソッド本体を分離するために演算子を使用し、return キーワードも省略します)。

Student aStudent = students.Find(s => s.Id == id);

ここでの魔法は、コンパイラが舞台裏で上記のようなクラスを生成することです。そのクラスには、述語シグネチャを持つメソッドがあり、id検索するキャプチャ用のフィールドもあります。

于 2012-12-01T09:25:16.897 に答える
1
于 2012-12-01T09:28:57.883 に答える
1

ラムダ演算子は、関数の引数を本体から分離します。

(arg1,arg2...argn)
=>
{
  //body
}

本体は括弧なしでもかまいません..しかし、それはまだ「本体」です。

(arg1,arg2..argn) => 1 ;

Student aStudent = students.Find(i=> i.Id== id);

Find は、ラムダ式を取る Linq メソッドです。

それは学生の各要素を通過します。

要素は (もっと理にかなってiいますが) で表され、「本体」に渡されます。Find メソッドが要素を返すstudent場合。i.Id==idstudent

于 2012-12-01T09:30:31.863 に答える
1
  • 何をしstudents.Find(i=> i.Id== id)ますか?

状況はこうです。Student オブジェクトのリストと、関心のある学生の ID があります。学生オブジェクトが、ID を取得してその ID を持つ学生を返す Find メソッドを持つ自分で定義したコレクションに格納されている場合、コードは次のようになります。次のようになります。

Student aStudent = students.Find(id);

しかし、Microsoft が一般的な List コレクションを定義したとき、それがどのように使用されるかを知ることはおそらくできませんでした。また、知りたくありませんでした。彼らは、Student オブジェクトやその他の考えられる種類の型で使用する機会を提供したいと考えていました。しかし、それは、あなただけが知っているあなたの問題についての情報を提供することによって、彼らがあなたが求めている要素を見つける方法をあなたに与えなければならないことを意味しました. この特定の例では、あなたが持っている ID と一致する Id フィールドを持つ生徒リストに保存されている Student オブジェクトを探していることがわかります。私があなたにオブジェクトを与えた場合、それを と呼びましょiう。次のチェックを実行することで、それが探しているオブジェクトであるかどうかを知ることができます。

i.Id == id 

というオブジェクトを渡せばstudent、テストを実行できます。テストを実行することで、studentそれがあなたが求めているものであるかどうかを知ることができます。

学生.Id == id

(id がなく、Student オブジェクトを一意に決定する他の情報 (つまりキー) を持っていない場合は、別の条件を指定することをお勧めします。柔軟性は重要です!)

では、次の質問に行きましょう。

  • どういう意味ですか?

    コンベンションを作りましょう。学生オブジェクトを何と呼ぶか​​を決定し、目的の学生を選択する適切なチェックを提供します。その生徒を表す識別子を の左側に=>、チェック条件を右側に配置します。したがって、次のようなものを持つことができます:

    学生 => 学生.Id == id

iまたは、代わりに議論中の学生オブジェクトを参照したい場合は、次のようにstudent書くことができます

i => i.Id == id

今見てみましょう。これは何ですか?特定の Student オブジェクトが bool を返すものです。機能です!

  • =>記号の意味は何ですか?

    関数を定義する演算子です。引数は左側にあり、本体は右側にあります。

  • それはどのように機能しますか?

    List 引数と、ここで説明しているような関数を受け取り、Find メソッドを使用せずに一致する生徒を返す関数を作成する必要があるとします。たぶん、こんなことを書いていました。

    Student FindStudent(List students, Func match) { foreach(Student st in students) if(match(st)) return st; st を返します。}

    Func 型は Student から boolean までの関数の型であると想像できるでしょう。Predicate を使用することもできました。これは、Students の述語の型であると推測できます。

    ただし、マイクロソフトが既にこれを行っているため、私がこれを書いたり、自分で書いたりする必要はありません。Find()Microsoftがクラスのために書いたコードはList<T>、上記のように見えます。

それが役立つことを願っています!


これはあなたが尋ねたすべてをカバーするはずです。しかし、全体像を把握するには、以下も参照してください。


あなたに役立つかもしれないいくつかの別れのメモ:

  • ラムダ式は複数の引数を持つことができます (例: `(x,y) => x*x + y + 43')
  • ラムダ式の右辺は、コード ブロックである場合があります (例: `(x,y) => {return x*x + y + 43;}')
  • 文字列と bool 値を返す int パラメータを持つラムダ式の型は「Func」です
  • 文字列引数と何も返さない int 引数を持つラムダ式の型は「Action」です
于 2012-12-01T10:10:28.580 に答える
0

List<T>メソッドを定義しますFind(Predicate<T> match)

Predicate<T>署名に一致する任意のメソッドを参照できるデリゲートです

bool Predicate(T param)

あなたの場合Find、学生のリストでメソッドを呼び出しているList<Student>ため、Findメソッドは次のシグネチャに一致する関数を期待しています:

bool MyFindMethod(Student param)

クラスでそのようなメソッドを次のように定義できます。

bool MyFindMethod(Student param)
{
    // Logic goes here
}

Find次のようにメソッドに渡します。

students.Find(MyFindMethod)

使用しているメソッドは小さくて単純なので、クラスでメソッドを作成するオーバーヘッドは価値がないため、ラムダ式を使用すると、同じメソッドを非常に簡潔な方法で定義できます。

s => s.Id == id

次と同等です。

bool AnonymousMethod(Student param)
{
    return s.Id == id;
}

演算子の左側の=>項目はメソッドに渡されるパラメーターであり、演算子の右側の項目=>はメソッド本体です。

コンパイラーは、パラメーター (s私の例では) が型であることを十分Studentに理解できるので、これを指定する必要はありません。

別のタイプの EG のリストがある場合

public class Customer
{
    public string Name { get; set;}
}

public IList<Customer> customers = new List<Customer>();

Customerその場合、コンパイラは、パラメーターが学生ではなく型であると推測します。

customers.Find(c => c.Name == name);

パラメータには任意の名前を付けることができますが、式を簡潔にするために通常は 1 文字にすることに注意してください。

これらすべてを理解すれば、コードが

students.Find(i => i.Id == id)

基本的に、パラメーターとして a を受け取り、それを評価して、演算子Studentの右側の基準に一致するかどうかを確認するメソッドを呼び出しています。=>パラメータが基準を満たす場合 (つまり、学生が変数にId一致するid場合)、式は true を返します。これによりFind、一致が見つかったことがメソッドに通知され、このオブジェクトが返されます。

ここでWPFに関連する同様の質問に答えましたが、別のコンテキストの例が理解に役立つかもしれません.

于 2012-12-01T10:29:39.237 に答える