扩展方法语法与查询语法

我试图得到一个句柄,如果有一个好的时间来使用lambdaexpression式的标准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); 

他们非常相似,第二个例子更简洁一些,但是如果你不知道=>正在做什么,那么expression的可能性就会小一些。

除了写简洁的代码,使用扩展方法,而不是LINQ语法有其他的优点吗?

说实话,有时候一旦你开始使用function和动作,它可能是情景。 假设你正在使用这三个funcs:

  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; 

正如你所看到的,第一个replacelamdbaexpression式来获取用户名,第二个replace了一个lamdbaexpression式,用来检查ID是否低于10,让我们面对它,第三个现在应该很容易理解。

注意:这是一个愚蠢的例子,但它的工作。

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

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

在这个例子中,第二个是稍微不详细的,因为扩展方法可以充分利用Func,但是他的Linqexpression式不能,因为它只是查找布尔值而不是返回布尔值的Func。 但是,这是使用expression式语言可能更好的地方。 假设你已经有了一个不仅仅是一个用户的方法:

  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) 

没有lambdaexpression式,我真的不能调用这个方法。 所以现在我所要做的就是创build一个基于原始方法调用创build一个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 查询expression式时 ,自定义扩展方法不在关键字列表中。 它会看起来有点奇怪与其他关键字混合。

我正在使用一个名为Into的自定义扩展方法,它只需要一个string:

查询示例

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

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

我认为最好不要一起使用,select一个并坚持下去。

大多数情况下,这是个人的喜好,但在查询语法(Comprehension方法)中,并不是所有的操作符都可以像前面所说的那样。

我发现扩展方法的语法更符合我的代码的其余部分。 我在SQL中执行SQL。 使用扩展方法在彼此之间添加所有内容,也很容易build立自己的expression式。

只是我的两分钱。

因为我不能发表评论,所以我想在这里给一个编程工具的答案:​​为什么要为最后一个例子做一个全新的方法? 你不能只使用:

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

他们编译相同的,是相同的。 就个人而言,我更喜欢大多数事情的lambda(扩展)方法,只使用语句(标准),如果我正在做LINQ to SQL或否则试图模拟SQL。 我发现lambda方法用代码更好地stream动,而这些语句在视觉上分散注意力。

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

我喜欢使用查询语法,当它真的是一个查询,即一个懒惰的expression,按需求评估。

看起来像常规方法调用(方法语法或lambda语法)的方法看起来不够懒,所以我将其用作约定。 例如,

 var query = from p in Products where p.Name.Contains("foo") orderby p.Name select p; var result = query.ToList(); //extension method syntax 

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

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

这有助于我更好地区分这两种呼叫方式。 当然,在某些情况下,你将被迫使用方法语法,所以我的约定不够引人注目。