C#学习笔记 Linq

Linq的基本用法

Linq,语言集成查询(language intergrated query)是一组用于C#的扩展。使用Linq可以对集合等内存数据进行查询,还可以查询数据库(datebase)、XML(标准通用标记语言)数据,分别称为Linq to object,Linq to datebase和Linq to XML。这里谈的是Linq to object。
Linq的写法类似于数据库SQL语句的查询语法。

	from 变量名 in 集合 where 条件 select 结果变量

其中,变量名是一个临时变量,集合是数组或其他集合对象,条件一般是一个针对变量的逻辑表达式,而结果变量一般是针对变量名的表达式(可以是变量自己)。例如:

	from n in arr where n > 5 select n;

表示从数组arr中找到大于5的元素(n),并且最终选出这些n
如果是选出这些数的平方,则是:

	from n in arr where n > 5 select n * n;

针对满足条件的数,还可以先进行降序排序,然后再输出结果,如:

	from n in arr where n > 5 orderby n descending select n * n;

示例1

查询int数组中大于的数字,并按照大小顺序排列:

	static void Main(string[] args) {
		Random rnd = new Random();
		// 示例1,查询int数组中大于10的数字,并按照大小顺序排列:
		int[] arr = new int[20];
		for (int i = 0; i < arr.Length; i++) arr[i] = rnd.Next(20);
		var m = from n in arr where n > 10 orderby n descending select n;
		foreach (var n in m)
			Console.Write(n + " ");
		Console.WriteLine();
	}

运行结果:
在这里插入图片描述

从上面的例子可以看到,Linq查询语法跟SQL查询语法很相似,但它要将from放到前面,这样变量的类型才好推断,方便集成开发环境进行智能感知(intellisence)。
Linq查询的结果返回的是一个枚举器对象,实现了IEnumerable接口,这个对象的类型一般很复杂,用var类型来表示,让编译器自动推断其类型。这个var对象可以用foreach来进行遍历。有的Linq查询返回的结果是“可查询对象”,实现IQuerable接口,由于IQuerable接口是IEnumerable接口的子接口,可以对它进行更复杂的操作。
值得注意的是:这个枚举器var对象并没有开始执行真正的查询,只有当用foreach来进行遍历时,查询过程才真正地执行。

示例2

一个稍微复杂的Linq查询,使用group分组功能:

	static void Main(string[] args) {
		// 示例2,一个稍微复杂的Linq查询,使用group分组功能:
		string[] languages = { "Java", "C#", "C++", "Delphi", "VB.net", "VC.net", "Perl", "Python" };
		var query = from item in languages
					group item by item.Length into lengthGroups
					orderby lengthGroups.Key
					select lengthGroups;
		foreach (var group in query) {
			Console.WriteLine("strings of length{0}", group.Key);
			foreach (var str in group) {
				Console.WriteLine(str);
			}
		}
	}

运行结果:
在这里插入图片描述
在这个例子中,按照字符长短(length)对数据进行分组(group)并放入lengthGroups变量中,按分组的关键字(.Key)进行排序。所得到的枚举器用双重的foreach循环进行遍历。

Linq的查询方法

Linq定义了大约40个查询操作符,如selectfrominwhere以及orderby等。

1.Linq的两种写法

一种形式是查询表达式语法(query expression syntax),另一种更接近SQL语法的查询方式,可读性更好。
另一种形式是查询方法语法(method syntax),主要利用System.Linq.Enumerable类中定义的扩展方法和Lambda表达式方法进行查询。例如:

	List<int> arr = new List<int>() { 1, 2, 3, 4, 5, 6, 7 };
	var result = arr.Where(a => a > 3).Sum();
	Console.WriteLine(result);

这段代码中,用到了两个扩展方法。
一个是Where扩展方法,需要传入一个Func<int, bool>类型的泛型委托,它表示对一个元素(int类型的变量)进行判断(a > 3),返回值是bool类型。这里是直接把 a => a > 3这个Lambda表达式传递给了Where方法。
另一个是Sum扩展方法,它计算了Where扩展方法返回的集合的和。
使用where等子句,实际上是调用了Enumerable类中定义的扩展方法。

2.扩展方法

这里所谓的“扩展方法(extension methods)”是在static的类中定义的全局函数,它可以带this参数,表示对某种对象上施加以一个方法,编译器会自动地将它转成对扩展方法的调用。

示例

对String的扩展方法:

using System;
public static class ExtensionMethodString
{
	public static int WordCount(this string s) {
		string[] words = s.Split(" ,;.!".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
		return words.Length;
	}
}
class Demo
{
	static void Main(string[] args){
		string s = "Hello world,C#!";
		int cnt = s.WordCount();
		Console.WriteLine(cnt);
	}
}
output:
3

在这里,对string对象进行了扩展,添加了WordCount方法,但是不是在string类的内部添加的,而是单独定义了一个staticExtensionMethodString,其中定义了static方法WordCount,其第一个参数(string类型)前面加了个特殊的this,从而表明它是一个特殊的对string类型的扩展方法。编译器会将s.WordCount()自动翻译成ExtensionMethodString.WordCount调用。
扩展方法是一个很有用的机制,它在不改变原类的定义的情况下,给原来“添加”了一个方法,实际上是一种语法糖。
扩展方法是从C#3.0 开始引入的,它的作用之一就是为Linq服务的。在Linq技术上,.NET的设计者在类库中定义了一系列的扩展方法来方便用户操作集合对象,这些扩展方法构成了Linq的查询操作符。

3.Linq的查询运算符

Linq的各种查询运算符实际上是定义在System.Linq.Enumerable等类中的一系列扩展方法,这些扩展方法是对IEnumerable等对象的扩展。所以可以用var result = arr.Where(a => a > 3).Sum()这样的调用方法来进行调用。
Linq的标准查询运算符有多达40多个,如下表。这些方法中有一小部分可以有等价的查询表达式关键字,如where关键字等价于Where方法,类似的还有selectgrouporderbyjoin等。
在这里插入图片描述
从执行时间上来看,各个标准查询运算符可以分为两类,一类是立即执行,一类是延迟执行。返回单一值的方法(如AverageSum)会立即执行。而返回序列的方法会延迟查询执行,因为它返回一个可枚举(IEnumerable)的对象,只有当用foreach进行遍历或者再次施以Sum等操作时才会真正执行。也可以说,查询运算符分两类,一类是“中间点”(如Where),它可以继续施加其他查询运算符;一类是“结束的”(如Sum),它的结果不能再施加其他查询运算符。
下面是常用运算符及其简单介绍:
Where:过滤出满足条件的。
Select:取出元素(可以映射到新的对象)。
First:取出序列第一个元素。
Take:取出部分元素。
Single:取出序列的唯一一个元素,如果元素个数不是1个,则报错。
FirstOrDefault:取得序列第一个元素,如果没有一个元素,则返回默认值。
Distinct:取出序列中非重复元素。
Orderby:排序。
Reverse:反序。
Concat:连接两个序列;相当于SQL的Union all。
Contains:序列是否包含指定元素。
Except:获得两个序列的差集。
Intersect:获得两个序列的交集。
Average:计算平均值。
Min:最小元素。
Max:最大元素。
Sum:元素总和。
Count:元素数量。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值