延时执行的Enumerable类方法
LINQ标准查询运算法是依靠一组扩展方法来实现的。而这些扩展方法分别在System.Linq.Enumerable和System.Linq.Queryable这连个静态类中定义。
Enumerable的扩展方法采用线性流程,每个运算法会被线性执行。这种执行方法如果操作类似关系型数据库数据源,效率会非常低下,所以Queryable重新定义这些扩展方法,把LINQ表达式拆解为表达式树,提供程序就可以根据表达式树生成关系型数据库的查询语句,即SQL命令,然后进行相关操作。
每个查询运算符的执行行为不同,大致分为立即执行和延时执行。延时执行的运算符将在枚举元素的时候被执行。
Enumerable类位于程序集System.Core.dll中,System.Linq命名空间下,并且直接集成自System.Object,存在于3.5及以上的.NET框架中。Enumerable是静态类,不能实例化和被继承,其成员只有一组静态和扩展方法。
LINQ不仅能够查询实现IEnumerable<T>或IQueryable<T>的类型,也能查询实现IEnumerable接口的类型。
理解LINQ首先必须理解扩展方法
msdn是这样规定扩展方法的:“扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。 它们的第一个参数指定该方法作用于哪个类型,并且该参数以 this 修饰符为前缀。”
下面给个扩展方法的例子如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 扩展方法
{
/// <summary>
/// 为string类型定义一个扩展方法
/// </summary>
static class Helper
{
public static string MyExtenMethod(this string s)
{
return s.Substring(0, 2);
}
}
class Program
{
static void Main(string[] args)
{
string s = "扩展方法示例";
Console.WriteLine(s.MyExtenMethod());//调用
Console.ReadKey(false);
}
}
}
</div>
程序的运行结果如下:

为了方便理解和记忆,将常用的延时执行的Enumerable类方法成员分了下组,具体如下:
1.Take用于从一个序列的开头返回指定数量的元素
2.TakeWhile 用于获取指定序列从头开始符合条件的元素,直到遇到不符合条件的元素为止
3.Skip跳过序列中指定数量的元素
4.SkipWhile 用于跳过序列总满足条件的元素,然会返回剩下的元素
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 延时执行的Enumerable类方法
{
class Program
{
static void Main(string[] args)
{
string[] names = { "DebugLZQ","DebugMan","Sarah","Jerry","Tom","Linda","M&M","Jeffery"};
//1.Take用于从一个序列的开头返回指定数量的元素
//
//a.在数组上直接使用Take方法
foreach (string name in names.Take(3))
{
Console.Write("{0} ", name);
}
Console.WriteLine();
Console.WriteLine("-----");
//b.在LINQ返回的IEnumerable<T>序列上使用Take方法
var query = from string name in names
where name.Length <=3
select name;
foreach (string name in query.Take(1))
{
Console.Write("{0} ",name);
}
Console.WriteLine();
Console.WriteLine("----------------------------");
Console.ReadKey(false);
//2.TakeWhile 用于获取指定序列从头开始符合条件的元素,直到遇到不符合条件的元素为止
//
var takenames = names.TakeWhile(n => n.Length>4);
var takenames2 = names.TakeWhile((n,i)=>n.Length<10&&i<3);
foreach (string name in takenames)
{
Console.Write("{0} ", name);
}
Console.WriteLine();
Console.WriteLine("-----");
foreach (string name in takenames2)
{
Console.Write("{0} ", name);
}
Console.WriteLine();
Console.WriteLine("----------------------------");
Console.ReadKey(false);
//3.Skip跳过序列中指定数量的元素
//
foreach (string name in names.Skip(5))
{
Console.Write("{0} ", name);
}
Console.WriteLine();
Console.WriteLine("-----");
var query_skip = (from name in names
where name.Length >= 3
select name).Skip(2);
foreach (string name in query_skip.Skip(2) )
{
Console.Write("{0} ", name);
}
Console.WriteLine();
Console.WriteLine("----------------------------");
Console.ReadKey(false);
//4.SkipWhile 用于跳过序列总满足条件的元素,然会返回剩下的元素
//跳过名字长度大于3的
var takenames_SkipWhile = names.SkipWhile(n => n.Length >3);
foreach (string name in takenames_SkipWhile)
{
Console.Write("{0} ", name);
}
Console.WriteLine();
Console.WriteLine("-----");
var takenames_SkipWhile2 = names.SkipWhile((n,i)=>n.Length>3&&i>2);
foreach (string name in takenames_SkipWhile2)
{
Console.Write("{0} ", name);
}
Console.WriteLine();
Console.WriteLine("----------------------------");
Console.ReadKey(false);
//小结Take、Skip获得第N到第M个元素
var names_TakeAndSkip = names.Skip(5).Take(3);
var names_TakeAndSkip2 = (from name in names
select name).Skip(5).Take(3);
foreach (string name in names_TakeAndSkip)
{
Console.Write("{0} ", name);
}
Console.WriteLine();
Console.WriteLine("-----");
foreach (string name in names_TakeAndSkip2)
{
Console.Write("{0} ", name);
}
Console.WriteLine();
Console.WriteLine("----------------------------");
Console.ReadKey(false);
}
}
}
</div>
程序中有详细的注释不再多做说明,程序运行结果如下:

5.Reverse用于翻转序列中的元素的顺序
6.Distinct过滤掉重复的元素
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Reverse_Distinct等
{
class Program
{
static void Main(string[] args)
{
string[] names = { "DebugLZQ", "Jerry", "Sarah", "Jerry", "Tom", "Linda", "M&M", "Jeffery" };
//5.Reverse用于翻转序列中的元素的顺序
string str = "反转字符串";
var strre = str.ToCharArray().Reverse();
var takenames = names.Reverse();
foreach (var c in strre)
{
Console.Write(c);
}
Console.WriteLine();
Console.WriteLine("-----");
foreach (var c in takenames )
{
Console.WriteLine(c);
}
Console.WriteLine("----------------------------");
Console.ReadKey(false);
//6.Distinct 过滤掉重复的元素
var takenames_Distinct = names.Distinct();
foreach (var c in takenames_Distinct)
{
Console.WriteLine(c);
}
Console.WriteLine("----------------------------");
Console.ReadKey(false);
}
}
}
</div>
程序的运行结果如下:

7.Union用于合并两个序列,并去掉重复项
8.Concat用于连接两个序列,不会去掉重复项
9.Intersect用于获得连个序列的交集
10.Except用于获得两个结合的差集
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Union_Concat_Intersect_Except
{
/// <summary>
/// DebugLZQ
/// http://www.cnblogs.com/DebugLZQ
/// </summary>
class Program
{
static void Main(string[] args)
{
string[] names1 = { "DebugLZQ", "Jerry", "Sarah", "Jerry", "Tom", "Linda", "M&M", "Jeffery" };
string[] names2 = {

