LINQ到对象的位置和时间?

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

显然,我可以在没有LINQ的情况下做任何事情。 那么在哪些操作中LINQ实际上可以帮助我编写更短和/或更可读的代码?

这个问题引发了这个问题

我发现LINQ to Objects在所有地方都很有用。 它解决的问题非常普遍:

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

这是我经常遇到的情况。 有很多编程领域基本上涉及将一个集合(或数据流)转换为另一个集合。 在这些情况下,使用LINQ的代码几乎总是更短且更易读。 我想指出LINQ不应该被认为是查询表达式的同义词 – 如果只需要一个运算符, 那么正常的“点符号”(使用扩展方法)通常可以更短且更易读 。

我特别喜欢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表达式,扩展方法)可能非常有用。

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

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

  • 在哪里 只需写一个foreach循环和一个“if”
  • 选择 。 创建目标类型的空列表,循环原始文件,转换每个目标类型并将其添加到结果中。
  • OrderBy 。 只需将其添加到列表中并调用.Sort()即可。 或实施冒泡排序;)
  • 然后(从PropertyA订购,然后由PropertyB订购)。 相当难一点。 自定义比较器和Sort应该可以解决问题。
  • GroupBy – 创建一个Dictionary>并遍历所有项目。 如果没有密钥存在,则创建它,然后将项添加到适当的列表中。

在每种情况下,过程方式都需要比LINQ方式更多的代码。 在“if”的情况下,它更多几行; 在GroupBy或OrderBy / Then的情况下,它还有很多。

现在采取一种将它们组合在一起的常见情况。 你突然想到一个10-20线的方法,可以用LINQ中的3-4线来解决。 LINQ版本保证更易于阅读(一旦熟悉LINQ)。

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

LINQ在以下几种情况下非常有用:

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

当您开始对复杂数据类型进行复杂过滤时,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; 

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

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

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

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

能够使用更高阶的函数会让你更通用。 因此,您将开始看到您可以简单地传递lambda并解决更整洁,更清洁的问题。 在这一点上,你会发现只有使用generics才能真正起作用。 当然,这是一个2.0function,但是当您传递函数时,使用情况会更加普遍。

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

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