2011-12-15 8 views
3

私は本からプロジェクトを実装していますが、なぜ私はこれらのラムダが必要なのか多少混乱しています。ラムダの使い方は私を混乱させます

public class Cart 
{ 
    private List<CartLine> lineCollection = new List<CartLine>(); 
    public class CartLine 
    { 
     public Product Product { get; set; } 
     public int Quantity { get; set; } 
    } 
    public void RemoveLine(Product product) 
    { 
     lineCollection 
      .RemoveAll(p => p.Product.ProductID == product.ProductID); 
    } 
} 

はなぜ.RemoveAll(p=> p.Product.ProductID == product.ProductID)が必要なのですか? .RemoveAllラムダ式が必要ですか?私はなぜthis.Product.ProductIDを使用できないのか分かりません。私はProductがリストであることを認識しています。p=> P.Productは何らかの反復を行い、必要なものが見つかるまで値を比較していますか?

製品は、私は、一般的に物事のこれらの種類のラムダの目的に関しては混乱している

public class Product 
{ 
    public int ProductID { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public decimal Price { get; set; } 
    public string Category { get; set; } 
} 

で定義されています。 p=>p.Product.ProductID == product.ProductID Lambdaを使用していないことが分かりましたので、私はそれが何の略語なのかを理解することができましたか?

私はこの1つの周りに私の頭を包み込むように見えることができないし、事前に感謝します。

答えて

2

RemoveAll実装には、反復ごとに無名関数を呼び出すイテレータがあります。同様に:

iterator { 
    your_lambda_function(current_item); 
} 

そしてp => p.Product.ProductID == product.ProductIDのように書き換えることができます:あなたのために少し明確になります

delegate(CartLine p) { return p.Product.ProductID == product.ProductID; } 

+0

ああ、そんなに意味があります。したがって、これらの実装にはイテレータが含まれており、各アイテムを解決する方法を渡しています。 は、だから私は、私はこれらすべてのLINQのものはイテレータが含まれていない推測しています、そして、イテレータでから一つの質問をセットを構築するために何 をしてください解決するための関数を渡して理解しています。私はいくつかのセットを解決するための商品コードを使用しているようではないbecaues私はその上で穏やかに困惑している別のクラスのように参照[これは製品である] .OrderByた(p => p.ProductID) 、それは何とかとしてそれを使用しています基準?これはProductIDへの参照と同様に機能しますか? – Jordan

+1

@Jordan:いいえ、 'OrderBy'の例では、コレクションがソートするためにコレクションが使用する値を返すために使用されるラムダを渡すだけです。 'p => generate-random-value'を渡して毎回ランダムな順序を得ることができます。したがって、これは 'ProductID'への参照ではなく、ちょうどある値です。ラムダ式は(この場合のように)必要に応じて委任に変換されますが、コンテキストは、それを必要とする場合、それはまた、式ツリーであってもよいこと – zerkms

1

ラムダは必要ありません。同じシグネチャを実装するメソッドの名前で置き換えることもできます。

6

デリゲートの省略形です。あなたのケースでは、ラムダない同じコードは次のようになります

public void RemoveLine(Product product) 
    { 
     var helper = new RemoveAllHelper(); 
     helper.product = product; 

     lineCollection.RemoveAll(helper.TheMethod); 
    } 

    class RemoveAllHelper 
    { 
     public Product product; 
     public bool TheMethod(CartLine p) { return p.Product.ProductID == product.ProductID; } 
    } 

あなたのラムダラムダ(「バウンド」または「捕獲」変数と呼ばれる)の外で定義された変数が含まれているため、コンパイラがしなければなりませんその変数を入れるフィールドを持つヘルパーオブジェクトを作成します。バインド変数なしのラムダについて

は、静的メソッドを使用することができる。

public void RemoveLine(Product product) 
    { 
     lineCollection.RemoveAll(TheMethod); 
    } 

    public static bool TheMethod(CartLine p) { return p.Product.ProductID == 5; } 

のみ結合した変数は、同じオブジェクトのインスタンスメソッドを利用することができるthisある:

public void RemoveLine(Product product) 
    { 
     lineCollection.RemoveAll(this.TheMethod); 
    } 

    public bool TheMethod(CartLine p) { return p.Product.ProductID == this.targetProductID; } 
+1

注 - http://msdn.microsoft.com/en-us/library/bb397687.aspx。 –

+2

@AlexeiLevenkov:すぐに不要な複雑さを追加しないでください。 OPが一度に一つのことを学ばせてください。 –

1

通常のように削除することもできます。

public void RemoveLine(Product product) { 
    for (var i = 0; i < lineCollection.Count;) { 
     if (lineCollection[i].Product.ProductID == product.ProductID) { 
      lineCollection.RemoveAt(i); 
     } else { ++i; } 
    } 
} 

私はラムダが良いと思う。 (実際には、このコードを見ると、なぜluncdasや名前付き関数であっても、より理解しやすいコードを作るための関数を使うことが示されるはずです)。

2

ReSharperの試用版をダウンロードしてください。 alt-enterを押して、あなたが望むものを選択するだけで、ラムダから代理人に名前付き関数などに変換することができます。それが何が何だったのかを理解するのを助けたのです。

関連する問題