繁体   English   中英

扩展方法语法与查询语法

[英]Extension methods syntax vs query syntax

如果有时间使用标准linq关键字或linq扩展方法与lambda表达式,我正试图处理。 他们似乎做同样的事情,只是写得不一样。 这纯粹是风格问题吗?

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语法还有其他优点吗?

老实说,有时一旦你开始使用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)

所以你可以看到,有时可能更容易使用查询方法。

使用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");

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

我认为不要一起使用它们并选择一个并坚持下去是个好主意。

它主要是个人品味,但在查询语法(理解方法)中,并非所有运算符都可用,如前所述。

我发现扩展方法语法更符合我的其余代码。 我在SQL中执行SQL。 只需使用扩展方法在彼此之上添加所有内容,构建表达式也非常容易。

只是我的两分钱。

由于我还不能发表评论,我想在这里找到编程工具的答案:​​为什么要为最后一个例子制作一个全新的方法? 你不能只使用:

.Where(user => IDIsBelowNumber(user, 10, true))

他们编译相同,并且是等价的。 就个人而言,我更喜欢lambda(扩展)方法,只使用语句(标准),如果我正在使用LINQ to SQL或尝试模拟SQL。 我发现lambda方法在代码中更好地流动,而语句在视觉上分散注意力。

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

我喜欢在它真正的查询时使用查询语法,即一个按需评估的惰性表达式。

看起来像常规方法调用(方法语法或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();

它可以帮助我更好地区分这两种风格的电话。 当然,有些情况下你会被迫使用方法语法,所以我的约定不够引人注目。

扩展方法/ lynda表达式的一个优点是提供了额外的运算符,如Skip和Take。 例如,如果要创建分页方法,则可以轻松实现跳过前10条记录并接下来的10条记录。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM