何时在LINQtoObjects上对lambda使用扩展方法来过滤集合?

时间:2020-03-05 18:38:27  来源:igfitidea点击:

我正在制作一些C3集合过滤器的原型,并遇到了这个问题。
我有一些产品:

public class MyProduct
{
    public string Name { get; set; }
    public Double Price { get; set; }
    public string Description { get; set; }
}

var MyProducts = new  List<MyProduct>
{            
    new  MyProduct
    {
        Name = "Surfboard",
        Price = 144.99,
        Description = "Most important thing you will ever own."
    },
    new MyProduct
    {
        Name = "Leash",
        Price = 29.28,
        Description = "Keep important things close to you."
    }
    ,
    new MyProduct
    {
        Name = "Sun Screen",
        Price = 15.88,
        Description = "1000 SPF! Who Could ask for more?"
    }
};

现在,如果我使用LINQ进行过滤,则可以按预期工作:

var d = (from mp in MyProducts
             where mp.Price < 50d
             select mp);

如果我将Where扩展方法与Lambda结合使用,则过滤器也可以正常工作:

var f = MyProducts.Where(mp => mp.Price < 50d).ToList();

问题:有什么区别,为什么要一个使用另一个?

解决方案

回答

LINQ变成了像我们拥有的代码一样的方法调用。

换句话说,应该没有区别。

但是,在两段代码中,我们不会在第一个代码中调用.ToList,因此第一段代码将产生一个可枚举的数据源,但是如果在其上调用.ToList,则两者应该是相同的。

回答

除了ToList的区别外,#2是更易读和更自然的IMO

回答

如前所述,d将是IEnumerable &lt;MyProduct>,而f是List &lt;MyProduct>

转换由Ccompiler完成

var d = 
    from mp in MyProducts
    where mp.Price < 50d
    select mp;

转换为(在编译为IL并扩展泛型之前):

var d = 
    MyProducts.
    Where<MyProduct>( mp => mp.Price < 50d ).
    Select<MyProduct>( mp => mp ); 
    //note that this last select is optimised out if it makes no change

注意,在这种简单情况下,它几乎没有什么区别。 Linq变得真正有价值的地方是更为复杂的循环。

例如,当等效的.Method()。Method.Method()变得复杂时,该语句可能包含分组依据,订单和一些let语句,并且仍然可以Linq格式读取。

回答

用于d的语法将被编译器转换为与扩展方法相同的IL。 " SQL式"语法被认为是表示LINQ表达式的更自然的方式(尽管我个人更喜欢扩展方法)。正如已经指出的,由于调用ToList(),第一个示例将返回IEnumerable结果,而第二个示例将返回List结果。如果在第二个示例中删除ToList()调用,它们将都返回与Where返回IEnumerable结果相同的结果。