2011-12-15 81 views
3

所以我正在從一本書中實現一個項目,我對於爲什麼需要這些lambda表達式感到有點困惑。Lambda的使用讓我感到困惑

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需要lambda表達式嗎?我不知道爲什麼我不能使用this.Product.ProductID,我意識到產品是一個列表,是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; } 
} 

我一般困惑,lambda表達式在這些事情的目的定義。是否有一些與p=>p.Product.ProductID == product.ProductID 等同的東西我看不到使用Lambdas,所以我可以更多地瞭解它是什麼速記?

我似乎無法將我的頭圍繞在這一個,並提前感謝。

回答

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事物都包含迭代器。我在另一個類中看到[這是在一個產品] .OrderBy(p => p.ProductID) 我有點困惑,因爲它不像使用ProductID來解決某些設置,它以某種方式將它用作一個標準?它的功能就像對ProductID的引用一樣嗎? – Jordan 2011-12-15 01:46:10

+1

@Jordan:nope,在`OrderBy`示例中,您只需傳遞將用於返回集合用於排序的值的lambda。你可以傳遞`p => generate-random-value`並且每次都得到隨機排序。所以它不是對`ProductID`的引用,而只是一些價值。 – zerkms 2011-12-15 01:49:21

1

Lambda表達式是不需要的。您也可以用實現相同簽名的方法的名稱替換它們。

6

它們是代表的簡寫。在你的情況,不用lambda表達式相同的代碼是這樣的:

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; } 
    } 

因爲你的拉姆達包含一個拉姆達之外定義一個變量(稱爲「綁定」或「俘獲」變量),編譯器必須用一個字段創建一個幫助對象來放入該變量。

對於無約束變量的lambda中,可以使用一個靜態方法:

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

您也可以像定期一樣去除它們。

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

雖然我認爲lambda更好。 (實際上,看這個代碼應該證明爲什麼使用函子(不管它們是lambda函數還是命名函數)使得代碼更容易理解)。

2

下載試用版ReSharper;它可以讓你從lambda轉換爲代表到命名函數等,只需按alt-enter並選擇你想要的。這正是幫助我學會了解什麼是什麼的原因。