何时何地使用 LINQ to Objects?

Posted

技术标签:

【中文标题】何时何地使用 LINQ to Objects?【英文标题】:Where and When to use LINQ to Objects? 【发布时间】:2010-10-09 01:57:37 【问题描述】:

在哪些情况下我应该使用 LINQ to Objects?

显然我可以在没有 LINQ 的情况下做任何事情。那么在哪些操作中 LINQ 真正帮助我编写更短和/或更具可读性

This question triggered by this

【问题讨论】:

【参考方案1】:

我发现 LINQ to Objects 在所有地方都很有用。它解决的问题很笼统:

您有一些数据项的集合 您需要另一个集合,该集合由原始集合形成,但经过某种转换或过滤。这可能是排序、投影、应用谓词、分组等。

这是我经常遇到的情况。有很多编程领域基本上涉及将一个集合(或数据流)转换为另一个。在这些情况下,使用 LINQ 的代码几乎总是更短且更易读。我想指出,LINQ 不应被视为查询表达式的同义词——如果只需要一个运算符,the normal "dot notation" (using extension methods) can often be shorter and more readable。

我特别喜欢 LINQ to Objects 的原因之一是它如此通用 - 而 LINQ to SQL 可能只涉及您的数据层(或几乎成为数据层) , LINQ to Objects 适用于每一层,适用于各种应用程序。

举个例子,这是我的 MiniBench 基准测试框架中的一行代码,将 TestSuite(基本上是一个命名的测试集合)转换为 ResultSuite(一个命名的结果集合):

return new ResultSuite(name, 
    tests.Select(test => test.Run(input, expectedOutput)));

如果ResultSuite 需要针对某些特定的“标准”结果进行缩放:

return new ResultSuite(name, 
    results.Select(x => x.ScaleToStandard(standard, mode)));

如果没有 LINQ,编写此代码不会困难,但 LINQ 只是让它更清晰,让您专注于真正的“逻辑”,而不是迭代循环和添加结果的细节到列表等。

即使 LINQ 本身不适用,为了 LINQ 而主要包含的一些功能(例如,隐式类型的局部变量、lambda 表达式、扩展方法)也可能非常有用。

【讨论】:

【参考方案2】:

答案几乎无处不在浮现在脑海中。一个更好的问题是何时使用它。

【讨论】:

好吧,做一个 HTTP 请求,多线程,那又如何,我们应该在 LINQ 中编写所有内容吗? 执行 HTTP 请求就是一个很好的例子。如果您将 lambda 语法作为 LINQ 的一部分(如果不这样做会很奇怪),那么将您的回调定义为闭包会使它更加更容易。 无论您的回答多么简洁,多一点反馈会更好。将来尝试以更多背景为基础来建立您的意见,以便我们可以更好地受到它的影响。除此之外,我确实对你的回答有点微笑,因为从表面上看,这是真的! PLINQ 何时可用? VS 2010? 你见过 LINQ 中的光线追踪器吗?有点极端,但证明了一点:LINQ 几乎可以被滥用于任何事情。【参考方案3】:

LINQ 非常适合“滑坡”。想一想许多常见操作中涉及的内容:

在哪里。只需编写一个 foreach 循环和一个“if” 选择。创建一个目标类型的空列表,遍历原件,转换每一个并将其添加到结果中。 订购方式。只需将其添加到列表并调用 .Sort()。或者实现冒泡排序;) ThenBy(按 PropertyA 排序,然后按 PropertyB 排序)。比较难。自定义比较器和排序应该可以解决问题。 GroupBy - 创建一个Dictionary<key, List<value>> 并遍历所有项目。如果不存在密钥,请创建它,然后将项目添加到适当的列表中。

在每种情况下,过程方式都比 LINQ 方式需要更多的代码。在“如果”的情况下,它多出几行;在 GroupBy 或 OrderBy/ThenBy 的情况下,它更多。

现在采取一个非常常见的场景,将它们组合在一起。你突然看到了一个 10-20 行的方法,它可以在 LINQ 中用 3-4 行来解决。并且保证 LINQ 版本更易于阅读(一旦您熟悉 LINQ)。

那么你什么时候使用 LINQ?我的回答:每当你看到“foreach” :)

【讨论】:

【参考方案4】:

LINQ 在一些场景中非常有用:

您希望使用类型化的“业务实体”而不是数据表来更自然地访问您的数据(并且尚未使用 NHibernate 或 LLBLGenPro 之类的工具) 您希望使用类似 SQL 的语法查询非关系数据(这在查询列表等时非常方便) 您不喜欢大量的内联 SQL 或存储过程

【讨论】:

第二个要点不是 - 那将用于使用 LINQ 查询列表等【参考方案5】:

当您开始对复杂数据类型进行复杂过滤时,LINQ 就会发挥作用。例如,如果给您一个 People 对象列表,并且您需要收集该列表中所有医生的列表。使用 LINQ,您可以将以下代码压缩为单个 LINQ 语句:

(伪代码)

doctors = []
for person in people:
    if person is doctor:
        doctors.append(person)

(对不起,我的 C# 生锈了,类型检查语法可能不正确,但你明白了)

doctors = from person in people where person.type() == doctor select person;

【讨论】:

在那种情况下,我不会使用查询表达式 - 我只会做 people.Where(person => person is Doctor) 医生 = people.OfType()【参考方案6】:

编辑:在我回答后,我看到一个更改为“LINQ to Objects”。那好吧。

如果我们通过 LINQ 引用 System.Linq 中的所有新类型,以及新的编译器功能,那么它将有很多好处——它有效地将函数式编程添加到这些语言中。 (这是我见过几次的进展(虽然这主要是 C# -- VB 在当前版本中受到限制)。

显而易见的开始是任何与列表处理相关的事情都变得非常容易。很多循环可以消失。你得到什么好处?您将开始更多地以声明方式进行编程,这将导致更少的错误。切换到这种风格时,事情开始“正常工作”。 (我觉得 LINQ 查询语法不太有用,除非查询非常复杂,有很多中间值。在这些情况下,语法将解决所有问题,否则您必须传递元组。)

接下来,匿名方法的语言支持(在 C# 和下一版本的 VB 中)允许您以更短的方式编写更多的构造。例如,处理异步回调可以在启动它的方法中定义。在这里使用闭包将导致您不必将状态捆绑到一个不透明的对象参数中并在以后将其投射出来。

能够使用高阶函数让您的思维更加通用。所以你会开始看到你可以在哪里简单地传递一个 lambda 并更简洁地解决问题。此时,您会意识到只有使用泛型才能真正发挥作用。当然,这是 2.0 的一个特性,但在传递函数时使用更为普遍。

在那里,您会进入收益递减点。声明和使用 func 以及声明所有泛型类型参数(在 C# 和 VB 中)的成本相当高。编译器不会为您解决问题,因此您必须手动完成所有操作。这会增加大量开销和摩擦,从而限制了您可以走多远。

那么,这就是“LINQ”吗?也许取决于营销。 LINQ 的推动使这种风格的 C# 编程变得更加容易,并且所有 LINQ 都基于 FP 思想。

【讨论】:

以上是关于何时何地使用 LINQ to Objects?的主要内容,如果未能解决你的问题,请参考以下文章

LINQ to SQL class LINQ to sql Objects?

从LINQ开始之LINQ to Objects(上)

从LINQ开始之LINQ to Objects(上)

Linq之旅:Linq入门详解(Linq to Objects)

LINQ to objects

从LINQ开始之LINQ to Objects(下)