在C#3.0中,对语言添加语言集成查询(LINQ)永远改变了查询和操作集合的方式。从那时起,如果您使用迭代语句来操作集合,那么您可能不应该使用LINQ。
一些C#程序员甚至不知道LINQ的存在,但幸运的是,这个数字变得越来越小。但是,许多人仍然认为,由于LINQ关键字和SQL语句之间的相似性,它的唯一用途是在查询数据库的代码中。
虽然数据库查询是LINQ语句的一种非常普遍的用法,但它们实际上可以处理任何可枚举的集合(即,实现IEnumerable接口的任何对象)。例如,如果您有一个帐户数组,而不是编写一个C#List foreach:
你可以写:
虽然这是如何避免这种常见的C#编程问题的一个非常简单的示例,但是有些情况下,单个LINQ语句可以轻松地替换代码中的迭代循环(或嵌套循环)中的许多语句。较少的代码通常意味着引入错误的机会较少。但请记住,在性能方面可能需要权衡。在性能关键的场景中,特别是在迭代代码能够对LINQ无法做出的集合进行假设的情况下,请确保在两种方法之间进行性能比较。
LINQ非常适合抽象操作集合的任务,无论它们是内存中对象,数据库表还是XML文档。在完美的世界中,您不需要知道底层对象是什么。但这里的错误是假设我们生活在一个完美的世界。实际上,如果该数据恰好采用不同的格式,则在完全相同的数据上执行时,相同的LINQ语句可以返回不同的结果。
例如,请考虑以下声明:
如果其中一个对象account.Status等于“活动”(注意大写字母A)会发生什么?好吧,如果myAccounts是一个DbSet对象(使用默认的不区分大小写的配置设置),where表达式仍将匹配该元素。但是,如果myAccounts是在内存数组中,它将不匹配,因此会产生不同的总结果。
但等一下。当我们之前谈到字符串比较时,我们看到==操作员执行了字符串的序数比较。那么为什么在这种情况下==操作员执行不区分大小写的比较呢?
答案是,当LINQ语句中的基础对象是对SQL表数据的引用时(与本示例中的Entity Framework DbSet对象的情况一样),该语句将转换为T-SQL语句。然后,运算符遵循T-SQL编程规则,而不是C#编程规则,因此上述情况下的比较最终不区分大小写。
通常,尽管LINQ是查询对象集合的有用且一致的方法,但实际上您仍然需要知道您的语句是否会被转换为C#以外的其他内容以确保代码的行为将在运行时如预期的那样。