刚刚接触LINQ,对这个语言集成查询(Language INtegrated Query)还很懵懂,遂记录下学习心得,方便以后查阅。
LINQ的写法形式有点像SQL,但它跟SQL是没有任何关系,它的作用主要就是用来处理对象的集合。
下面以一个简单的例子来展示LINQ的强大之处:
如:我要在一批电影集合中找出票价最便宜的前3部电影,下面的代码是以前的做法形式:
static void Main(string[] args)
{
//构造一个对象集合
Movie[] movies =
{
new Movie{Name="晚秋",artist="汤唯",price=25.5M},
new Movie{Name="少林足球",artist="周星驰",price=35.7M},
new Movie{Name="叶问",artist="甄子丹",price=15.5M},
new Movie{Name="无间道",artist="刘德华",price=45.5M},
new Movie{Name="霸王别姬",artist="张国荣",price=50M},
new Movie{Name="邻家特工",artist="成龙",price=25.5M}
};
//用来保存查询结果
Movie[] ms = new Movie[3];
//按照价格属性重新排序
Array.Sort(movies, (item1, item2) => {
return Comparer<decimal>.Default.Compare(item1.price, item2.price);
});
//前3项拿出来
Array.Copy(movies, ms, 3);
foreach (var item in ms)
{
Console.WriteLine(item.artist+"----"+item.Name+"----"+item.price);
}
Console.ReadLine();
}
}
public class Movie
{
public string Name { get; set; }
public string artist { get; set; }
public decimal price { get; set; }
}
现在,我直接用LINQ对此进行处理,看看结果如何:
static void Main(string[] args)
{
//构造一个对象集合
Movie[] movies =
{
new Movie{Name="晚秋",artist="汤唯",price=25.5M},
new Movie{Name="少林足球",artist="周星驰",price=35.7M},
new Movie{Name="叶问",artist="甄子丹",price=15.5M},
new Movie{Name="无间道",artist="刘德华",price=45.5M},
new Movie{Name="霸王别姬",artist="张国荣",price=50M},
new Movie{Name="邻家特工",artist="成龙",price=25.5M}
};
var results = from ms in movies
orderby ms.price ascending
select new { ms.artist, ms.Name, ms.price };
int i = 0;
foreach (var item in results)
{
Console.WriteLine(item.artist+"----"+item.Name+"----"+item.price);
if (i++==2)
{
break;
}
}
Console.ReadLine();
}
可以看到效果是一样的。相比老方式而言,使用LINQ清晰,容易看懂业务,也可以少敲很多繁杂代码。
但是,上面的LINQ也有缺点,就是引入了一个计数变量i,如果不引入,那么foreach会将所有元素打印出来。如果这样的计数变量多了,像什么i,j等乱七八糟的都有了之后,让人看了很是不舒服。怎么办呢?LINQ还有一种写法:
static void Main(string[] args)
{
//构造一个对象集合
Movie[] movies =
{
new Movie{Name="晚秋",artist="汤唯",price=25.5M},
new Movie{Name="少林足球",artist="周星驰",price=35.7M},
new Movie{Name="叶问",artist="甄子丹",price=15.5M},
new Movie{Name="无间道",artist="刘德华",price=45.5M},
new Movie{Name="霸王别姬",artist="张国荣",price=50M},
new Movie{Name="邻家特工",artist="成龙",price=25.5M}
};
var results = movies
.OrderBy(m=>m.price)
.Take(3)
.Select(a=>new{a.artist,a.Name,a.price});
foreach (var item in results)
{
Console.WriteLine(item.artist+"----"+item.Name+"----"+item.price);
}
Console.ReadLine();
}
这样,对于结果,就不用再引入计数器了。

还有一个值得一提的就是:LINQ的查询是延迟的,什么意思呢?就拿上面的例子来说,不执行foreach代码,那么上面LINQ的那段查询就不会执行。直到执行了foreach(即IEnumerable<T>结果中的条目被枚举时)才会执行查询。
可以测试一下:
static void Main(string[] args)
{
//构造一个对象集合
Movie[] movies =
{
new Movie{Name="晚秋",artist="汤唯",price=25.5M},
new Movie{Name="少林足球",artist="周星驰",price=35.7M},
new Movie{Name="叶问",artist="甄子丹",price=15.5M},
new Movie{Name="无间道",artist="刘德华",price=45.5M},
new Movie{Name="霸王别姬",artist="张国荣",price=50M},
new Movie{Name="邻家特工",artist="成龙",price=25.5M}
};
var results = movies
.OrderBy(m=>m.price)
.Take(3)
.Select(a=>new{a.artist,a.Name,a.price});
//加了这一句
movies[2] = new Movie { Name = "叶问", artist = "甄子丹", price = 10M };
foreach (var item in results)
{
Console.WriteLine(item.artist+"----"+item.Name+"----"+item.price);
}
Console.ReadLine();
}
查询结果是:
可见,上面的LINQ查询是在新加的语句执行之后才执行的。
那如果我不想让LINQ查询在新加的语句执行之后才执行,我想让它立刻执行,怎么弄呢?
很简单,在新加的语句之前,执行一次foreach,如下:
static void Main(string[] args)
{
//构造一个对象集合
Movie[] movies =
{
new Movie{Name="晚秋",artist="汤唯",price=25.5M},
new Movie{Name="少林足球",artist="周星驰",price=35.7M},
new Movie{Name="叶问",artist="甄子丹",price=15.5M},
new Movie{Name="无间道",artist="刘德华",price=45.5M},
new Movie{Name="霸王别姬",artist="张国荣",price=50M},
new Movie{Name="邻家特工",artist="成龙",price=25.5M}
};
var results = movies
.OrderBy(m=>m.price)
.Take(3)
.Select(a=>new{a.artist,a.Name,a.price});
foreach (var item in results)
{
Console.WriteLine(item.artist + "----" + item.Name + "----" + item.price);
}
//加了这一句
movies[2] = new Movie { Name = "叶问", artist = "甄子丹", price = 10M };
foreach (var item in results)
{
Console.WriteLine(item.artist+"----"+item.Name+"----"+item.price);
}
Console.ReadLine();
}
可以看到结果:LINQ查询了两遍!!!
其实除了foreach,还是有其它方式可以让LINQ立刻执行,比如:使用非延迟的扩展方法(如下面的Sum方法)。
static void Main(string[] args)
{
//构造一个对象集合
Movie[] movies =
{
new Movie{Name="晚秋",artist="汤唯",price=25.5M},
new Movie{Name="少林足球",artist="周星驰",price=35.7M},
new Movie{Name="叶问",artist="甄子丹",price=15.5M},
new Movie{Name="无间道",artist="刘德华",price=45.5M},
new Movie{Name="霸王别姬",artist="张国荣",price=50M},
new Movie{Name="邻家特工",artist="成龙",price=25.5M}
};
var results = movies
.OrderBy(m=>m.price)
.Take(3)
.Select(a=>new{a.artist,a.Name,a.price});
//LINQ执行查询
var sum = movies.Sum(e => e.price);
Console.WriteLine("Sum:"+sum);
//加了这一句
movies[2] = new Movie { Name = "叶问", artist = "甄子丹", price = 10M };
//LINQ执行查询
foreach (var item in results)
{
Console.WriteLine(item.artist+"----"+item.Name+"----"+item.price);
}
//LINQ执行查询
var sum1 = movies.Sum(e => e.price);
Console.WriteLine("Sum:" + sum1);
Console.ReadLine();
}
结果如下,可以看到LINQ执行了3次查询!!!
关于LINQ暂时就先记录到这啦。