linq 扩展方法语法与查询语法[重复]

hkmswyz6  于 2023-06-03  发布在  其他
关注(0)|答案(8)|浏览(174)

此问题已在此处有答案

Fluent and Query Expression — Is there any benefit(s) of one over other? [closed](14个回答)
2天前关闭。
我想知道现在是否适合在lambda表达式中使用标准linq关键字或linq扩展方法。他们似乎在做同样的事情,只是写得不一样。这纯粹是风格问题吗?

var query = from p in Products
    where p.Name.Contains("foo")
    orderby c.Name
    select p;

// or with extension methods:
var query = Products
    .Where(p => p.Name.Contains("foo"))
    .OrderBy(p => p.Name);

它们非常相似,第二个例子更简洁一些,但如果您不知道=>在做什么,则可能表达能力较差。

除了编写简洁的代码外,使用扩展方法相对于LINQ语法还有其他优势吗?

iyr7buue

iyr7buue1#

老实说,一旦你开始使用Funcs和Actions,有时它可能是情境性的。假设你正在使用这三个函数:

Func<DataClasses.User, String> userName = user => user.UserName;
  Func<DataClasses.User, Boolean> userIDOverTen = user => user.UserID < 10;
  Func<DataClasses.User, Boolean> userIDUnderTen = user => user.UserID > 10;

正如你所看到的,第一个替换了lamdba表达式来获取用户名,第二个替换了用于检查ID是否小于10的lamdba表达式,让我们面对它,第三个现在应该很容易理解。
注意:这是一个愚蠢的例子,但它工作。

var userList = 
    from user in userList
    where userIDOverTen(user)
    select userName;

对比

var otherList =
    userList
    .Where(IDIsBelowNumber)
    .Select(userName)

在这个例子中,第二个例子稍微不那么冗长,因为扩展方法可以充分利用Func,但Linq表达式不能,因为它只查找布尔值,而不是返回布尔值的Func。然而,这是使用表达式语言可能更好的地方。假设你已经有了一个方法,它接受的不仅仅是一个用户:

private Boolean IDIsBelowNumber(DataClasses.User user, 
          Int32 someNumber, Boolean doSomething)
  {
    return user.UserID < someNumber;
  }

注意:doSomething之所以存在,是因为where扩展方法可以接受一个用户和整数并返回布尔值的方法。这个例子有点烦人。
现在,如果你看一下Linq查询:

var completeList =
     from user in userList
     where IDIsBelowNumber(user, 10, true)
     select userName;

你会还的扩展方法:

var otherList =
    userList
    .Where(IDIsBelowNumber????)
    .Select(userName)

没有lambda表达式,我真的不能调用这个方法。所以现在我要做的是创建一个方法,该方法基于原始方法调用创建一个Func。

private Func<DataClasses.User, Boolean> IDIsBelowNumberFunc(Int32 number)
   {
      return user => IDIsBelowNumber(user, number, true);
   }

然后将其插入:

var otherList =
     userList
     .Where(IDIsBelowNumberFunc(10))
     .Select(userName)

因此,您可以看到,有时候使用查询方法可能更容易。

xeufq47z

xeufq47z2#

使用LINQ扩展方法(* 基于方法的查询 *)的一个优点是,您可以定义自定义扩展方法,并且它仍然可以读取。
另一方面,当使用LINQ * 查询表达式 * 时,自定义扩展方法不在关键字列表中。它看起来有点奇怪与其他关键字混合。

示例

我使用了一个名为Into的自定义扩展方法,它只接受一个字符串:

查询示例

var query = (from p in Products
    where p.Name.Contains("foo")
    orderby c.Name
    select p).Into("MyTable");

扩展方法示例

var query = Products
                   .Where(p => p.Name.Contains("foo"))
                   .OrderBy(p => p.Name)
                   .Into("MyTable");

在我看来,后者,使用一个 * 基于方法的查询 *,当你有自定义的扩展方法时,读起来更好。

quhf5bfb

quhf5bfb3#

我认为这是一个好主意,不要一起使用它们,选择一个并坚持使用它。
这主要是个人喜好,但在查询语法(理解方法)中,并不是所有的操作符都像前面所说的那样可用。
我发现扩展方法的语法与我的代码的其余部分更一致。我用SQL做我的SQL。构建表达式也很容易,只需使用扩展方法将所有内容添加到彼此之上即可。
只是我的两分钱。
因为我还不能发表评论,所以我想在这里对编程工具的答案做一个评论:为什么要为最后一个例子创建一个全新的方法??您不能用途:
.Where(user => IDIsBelowNumber(user, 10, true))

bxjv4tth

bxjv4tth4#

它们的编译方式相同,并且是等效的。就我个人而言,我更喜欢lambda(扩展)方法,只有在我做LINQ to SQL或试图模拟SQL时才使用语句(标准)。我发现lambda方法在代码中更流畅,而语句在视觉上会分散注意力。

lbsnaicq

lbsnaicq5#

当我使用没有查询语法等价物的Linq方法时,我更喜欢扩展方法语法,比如FirstOrDefault()或其他类似的方法。

wrrgggsh

wrrgggsh6#

扩展方法语法更简洁,可读性更强

  • 不通过Select进行转换。
  • 没有中间变量。
  • 没有通过SelectMany的笛卡尔积。

查询语法有很多优点,但最后不得不编写select p是一个糟糕的举动。当作为一个更大的方法链的一部分时,它也会更嘈杂。在下面的示例中,查询语法更简洁:

var result =
  from a in tableA
  from b in tableB
  where a.SomeValue == b.SomeValue
  select Compose(a, b) as p
  orderby p.rank
  select p.ToArray();
rjee0c15

rjee0c157#

我喜欢使用查询语法时,它真的是一个查询,即一个懒惰的表达式,评估的需求。
看起来像常规方法调用的方法(方法语法或lambda语法)看起来不够懒惰,所以我使用它作为约定。例如

var query = from p in Products
            where p.Name.Contains("foo")
            orderby p.Name
            select p;

var result = query.ToList(); //extension method syntax

如果它不是一个查询,我喜欢流畅的风格,在我看来,它与其他急切执行的调用一致。

var nonQuery = Products.Where(p => p.Name.Contains("foo"))
                       .OrderBy(p => p.Name)
                       .ToList();

它帮助我更好地区分两种风格的呼叫。当然,在某些情况下,你无论如何都必须使用方法语法,所以我的约定并不是很有说服力。

bcs8qyzn

bcs8qyzn8#

扩展方法/lynda表达式的一个优点是提供了额外的操作符,如Skip和Take。例如,如果您正在创建一个分页方法,那么能够跳过前10个记录并获取下10个记录是很容易实现的。

相关问题