Lambda的使用令我感到困惑

时间:2011-12-15 01:22:08

标签: c# asp.net lambda

所以我正在从书中实施一个项目,我有点困惑为什么我需要这些lambdas。

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,我意识到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; }
}

我常常对Lambdas在这些事情上的目的感到困惑。 p=>p.Product.ProductID == product.ProductID是否有一些平等的东西? 我可以看到没有使用Lambdas所以我可以更多地了解它是什么简写?

我似乎无法绕过这一个,并提前感谢。

5 个答案:

答案 0 :(得分:6)

他们是代表的简写。在您的情况下,没有lambdas的相同代码将如下所示:

    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包含一个在lambda之外定义的变量(称为“bound”或“captured”变量),所以编译器必须创建一个带有字段的辅助对象来放入该变量。

对于没有绑定变量的lambdas,可以使用静态方法:

    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 :(得分:2)

RemoveAll实现有一些迭代器,它为每次迭代调用你的匿名函数。像:

iterator {
    your_lambda_function(current_item);
}

p => p.Product.ProductID == product.ProductID可以改写为:

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

对你来说可能看起来更清楚

答案 2 :(得分:2)

下载ReSharper的试用版;它允许你从lambdas转换为委托到命名函数,只需按alt-enter并选择你想要的那个。这就是帮助我学会理解什么是什么的原因。

答案 3 :(得分:1)

不需要Lambda。您也可以使用实现相同签名的方法的名称替换它们。

答案 4 :(得分: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更好。 (事实上​​,查看此代码应该说明为什么使用仿函数(无论是lambdas还是命名函数)可以使代码更易理解。)