我通常更喜欢扩展方法,因为他们发现它们更容易阅读,但在看到Erno对这个问题的答案后,我想知道最小查询看起来如何只使用扩展方法?
更一般地说,是否存在可以在一种形式而不是另一种形式中创建的查询,或者两种方法是否相同?
xan*_*tos 10
来自ILSpy:
这个
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();
Run Code Online (Sandbox Code Playgroud)
是(有点清洁)和评论
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();
Run Code Online (Sandbox Code Playgroud)
我必须说实话,我唯一不知道怎么做"手工"的是两个from.我怀疑这是一个SelectMany,但它至少需要30分钟来破解它.如果你有兴趣,请参阅ILSpyOptions->Decompiler and deactivate "Decompile query expressions.
在查询表达式中没有什么可以做的,没有查询表达式就无法完成 - 无论如何,查询表达式只是被翻译成非查询表达式代码.有很多查询无法在查询表达式中编写,但是...例如,使用Select提供索引的重载的任何东西:
var foo = bar.Select((value, index) => new { value, index });
Run Code Online (Sandbox Code Playgroud)
......当然还有查询表达式根本不支持的所有运算符(First等等).
"最小值"的查询将使用SelectMany用于第二from条款,Select对于let条款(引入新的透明标识符),Where用于where子句和Select用于select子句.