2011-12-15 77 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并选择你想要的。这正是帮助我学会了解什么是什么的原因。