简体   繁体   English

Linq查询语法和扩展方法

[英]Linq query syntax and extension methods

I usually prefer the extension methods, because they i find them easier to read, but after seeing the answer by Erno to this question I was wondering how the minimum query would look with only extension methods used? 我通常更喜欢扩展方法,因为他们发现它们更容易阅读,但在看到Erno对这个问题的答案后,我想知道最小查询看起来如何只使用扩展方法?

And more generally, are there queries that you can create in one form but not the other, or are both approaches equivalent? 更一般地说,是否存在可以在一种形式而不是另一种形式中创建的查询,或者两种方法是否相同?

Taken from ILSpy: 来自ILSpy:

This 这个

var minimum = (from p1 in differenceList
                from p2 in differenceList
                let distance = Math.Abs(p1.X - p2.X)
                where !object.ReferenceEquals(p1, p2)
                orderby distance
                select new { Point1 = p1, Point2 = p2, Distance = distance }).First();

is (with a little cleaning) and with comments 是(有点清洁)和评论

var minimum = differenceList
    // The two from
    .SelectMany(
        p1 => differenceList, 
        (p1, p2) =>
        new {
            p1 = p1, 
            p2 = p2
        })
    // The let
    .Select(q => 
        new{
            q = q, 
            distance = Math.Abs(q.p1.X - q.p2.X)
        })
    // The where
    .Where(r => !object.ReferenceEquals(r.q.p1, r.q.p2))
    // The orderby
    .OrderBy(r => r.distance)
    // The final select
    .Select(r => new
    {
        Point1 = r.q.p1, 
        Point2 = r.q.p2, 
        Distance = r.distance
    })
    // The First
    .First();

I have to tell the truth, the only thing I didn't know how to do "by hand" was the two from . 我必须说实话,我唯一不知道怎么做“手工”的是两个from I suspected it was a SelectMany , but it would have taken me at least 30 minutes to crack it. 我怀疑它是一个SelectMany ,但它至少需要30分钟来破解它。 If you are interested, in ILSpy Options->Decompiler and deactivate "Decompile query expressions. 如果您有兴趣,请在ILSpy Options->Decompiler and deactivate "Decompile query expressions.

There's nothing you can do in query expressions which can't be done without query expressions - query expressions are just translated into non-query-expression code anyway. 在查询表达式中没有什么可以做的,没有查询表达式就无法完成 - 无论如何,查询表达式只是被翻译成非查询表达式代码。 There are plenty of queries that can't be written in query expressions though... for example, anything using the Select overload which provides the index as well: 有很多查询无法在查询表达式中编写,但是...例如,使用Select过载的任何东西都提供了索引:

var foo = bar.Select((value, index) => new { value, index });

... and of course, all the many operators which aren't supported by query expressions at all ( First etc). ...当然,所有许多运算符根本不受查询表达式的支持( First etc)。

The "minimum" query would use SelectMany for the second from clause, Select for the let clause (introducing a new transparent identifier), Where for the where clause, and Select for the select clause. “最小”查询将使用SelectMany用于第二个from子句, Select用于let子句(引入新的透明标识符), Where用于where子句, Select用于select子句。

Some querys can only be written using the extension method syntax(in particular there are extension methods the query syntax doesn't support). 某些查询只能使用扩展方法语法编写(特别是查询语法不支持的扩展方法)。 The extension method syntax supports everything the query syntax supports, since the query syntax gets compiled into the very same extension methods. 扩展方法语法支持查询语法支持的所有内容,因为查询语法被编译为完全相同的扩展方法。

On the other hand the query syntax has a few features which are a bit more verbose in the extension method syntax ( let and certain join s). 另一方面,查询语法具有一些在扩展方法语法( let和某些join s)中更加冗长的特性。

join can be replaced by SelectMany and let with a Select that introduces a anonymous type that includes both the actual variable in the query and the variable introduced in the let clause. join可以被替换SelectMany ,并let一个Select是引入了一个匿名类型既包括在查询中的实际变量和介绍的变量let条款。

A clean version in extension method syntax would look like this: 扩展方法语法中的干净版本如下所示:

differenceList
    .SelectMany(p1=>differencelist,(p1,p2) => new {Point1 = p1,Point2 = p2,
           Distance=Math.Abs(q.p1.X - q.p2.X)})
    .Where(e=>!object.ReferenceEquals(e.p1,e.p2))
    .OrderBy(e=>e.Distance)
    .First();

Every Linq expression can be expressed using extension methods. 每个Linq表达式都可以使用扩展方法表示。 The compiler translates Linq into them anyway. 无论如何,编译器将Linq转换为它们。 On the other hand, not every extension method can be expressed in Linq syntax. 另一方面,并​​非每种扩展方法都可以用Linq语法表示。

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

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