本文讨论的是使用C#,VB.NET及其他.NET语言下使用LINQ进行查询的方法,文中所给的代码都是C#。
LINQ是在.NET Framework3.5以后才引入的一种快速查询语句。在Linux系统中使用Mono2.0也支持LINQ语句。
LINQ语句的基本结构如下:
from 临时变量 inIEnumerable<T>接口的对象 where条件 [orderby条件] [groupby条件] select 需要选择的值
其中order by和group by是可选部分。
IEnumerable<T>接口的对象包括Array,List等。
需要注意的是,在LINQ中各个部分的顺序是不能够颠倒的!
可以看出LINQ语句与数据库查询的SQL语句是类似的,但是各个关键字的顺序是不同的。
SQL语句的结构为:
select ... from ... where ... [order by ...] [group by ...]
下面给出最基本的LINQ查询用法(查询对象为一般数组)
有如下的数组:
int[] num = new int[] { 2, 3, 4, 5 };
查询1. 查询大于3的数
var res = from n in num where n > 3 select n ;
在这一查询语句中,使用n作为查询变量,n指代的是数组num中的一个元素。
此处查询到的结果res的类型使用var代替,但其实际类型为IEnumerable<int>,而不是int[]。这是需要注意的,正因为如此,我们在输出查询结果的时候,要使用foreach语句。
foreach (var r in res)
Console.WriteLine(r);
而下面的一种写法是错误的,因为res的类型不是int[]。不可以用中括号进行索引
for (int i = 0; i < 2; i++)
Console.WriteLine(res[i]);
如果一定要写for循环,请将其转换为array再使用,下面的写法是正确的。
Console.WriteLine(res.ToArray()[i]);
对于上面的查询语句,也有简化版的写法,其中用到了lambda语句。
var res2 = num.Where(n => n > 3);
直接在数组后用.Where引出查询条件,其中n => n > 3是lambda语句表示对于数组中的元素n,选择大于3的。
查询2. 查询大于3的数,并求出这些数的平方
var res = from n in num where n > 3 select n * n ;
与查询1相比,变化就在于select中n变为了n * n
用简化写法就是这样的
var res = num.Where(n => n > 3).Select(n => n * n);
再给一种写法
var res = num.Select(n => n * n).Where(n => n > 3);
注意:这两种写法只是.Where与.Select的顺序不同,且这两种写法都没有语法问题。但是结果不同。
第一种写法的结果为:16,25。
第二种写法的结果为:4,9,16,25。
原因在于,简化写法中一个.Where和一个.Select都代表了一次查询,等于是都做了两次查询。第一种写法是先判断大小再平方,第二种写法是先平方再判断大小。而在标准写法中是只进行了一次查询。
查询3.查询大于3的数,并求出这些数的平方,并将这些数的平方按照降序排列
var res = from n in num where n > 0 orderby n * n descending select n * n;
降序是descending,升序是ascending。
此处orderby后面写的是n * n,虽然在此处如果只写n,在所给的数据的情况下是不会有影响的。但是要注意其执行顺序就是书写的顺序,先where选择,再orderby,最后select。如果我们改变num中的数据,出现负数时,如果orderby只写n,就会出错了。
使用简化写法如下:
var res = num.Where(n => n > 3).Select(n => n * n).OrderByDescending(n => n);
对于排序使用OrderBy语句时,升序和降序是语言所提供的,对于一些其他的排序法,如绝对值升序等,通用的方法是自己定义一个比较器。
比较器的定义可以参考(定义一个绝对值降序):
class MyComparer : IComparer<int>
{
public int Compare(int x, int y)
{
if (Math.Abs(x) > Math.Abs(y))
return -1;
else if (Math.Abs(x) < Math.Abs(y))
return 1;
else
return 0;
}
}
调用的时候写法:
MyComparer comparer = new MyComparer();
var res = num.Where(n => n > 3).Select(n => n).OrderBy(n => n, comparer);
当然,有需要时把比较器定义泛型实现是更好的,声明其变量类型为object。
文中所涉及的所有代码均在Visual Studio 2015中通过。