转载LINQ学习扩展方法,委托,Lambda表达式 第二篇 – 韩迎龙 – 博客园.
- LINQ基本查询操作符-获取数据
(1) select() 语法是:
public static IEnumerable<TResult> select<TSource,TResult>(
this IEnumerbale<TSource> source.
Func<TSource,TResult> selector)
说明:1) select方法本身是一个泛型扩展方法
2) 它作用于IEnumerable<TSource>类型
3) 他只接受一个Func<TSource,TResult>类型参数
4) Func<TSource,TResult>是一个泛型委托,位于System名字的空间下,System.Core.dll中,在这里Selector是一个提取器。
(2) 举例说明,先定义一个静态类ExtraClass,然后再静态类中在定义一个静态的扩展方法,实现输出信息。代码如下:
public static class ExtraClass
{
//为IEnumerable提供输出的方法
public static void Print(this IEnumerable<string> ie)
{
IEnumerator<string> result = ie.GetEnumerator();
while (result.MoveNext())
{
MessageBox.Show(result.Current);
}
}
}
然后如图所示,单击图上的按钮事件,在按钮事件中的代码是:
此事件下面的代码实现了将一个泛型集合中的数据循环显示出来,代码如下:
List<string> persons = new List<string>();
persons.Add(“zhang san”);
persons.Add(“zhang san feng”);
persons.Add(“li si”);
persons.Add(“wang wu”);
persons.Add(“wang liu”);
persons.Add(“li ba”);
persons.Add(“lao wu”);
persons.Add(“zhang xx”);
//输出persons里面的所有的元素
var result = persons.Select(p => p);
result.Print();
执行结果是按顺序循环输出。
2. LINQ基本查询操作符-过滤数据
(1) where() 语法是:
public static IEnumerable<TSource> where<TSource>(
this IEnumerable<TSource> source,
Func<TSource,bool> predicate)
说明:1) where方法是一个泛型扩展方法
2) 它和select()一样作用与IEnumerable<TSource>类型
3) 它只接受一个Func<TSource,bool>泛型委托参数,在这里predicate是一个判断条件。
(2) 举例说明,还是上面的例子,使用那个泛型集合,实现按照一定的条件输出信息。先创建一个方法,实现输出姓“zhang”的人的信息,代码如下:
public bool Judge(string s)
{
if (s.StartsWith(“zhang”))
{
return true;
}
return false;
}
在select控件的事件下面用LINQ代码输出只是姓张的各种各样的实现代码:
//输出persons里面姓“zhang”的人
//var result = persons.Where(p => p.StartsWith(“zhang”)); //第一种方法
//var result = persons.Select(p => p).Where(p => p.StartsWith(“zhang”)); //第二种方法
//var result = persons.Where(p => p.StartsWith(“zhang”)).Select(p => p); //第三种方法
var result = persons.Where(p => Judge(p)); //第四种方法
result.Print();
3. LINQ基本查询操作符-排序数据
(1) OrderBy() 语法是:
pblic static IOrderedEnumerable<TSource> orderBy<TSource,TKey>(
this IEnumerable<TSource> source
Func<TSource,TKey> keySelector)
注:1) orderBy方法也是一个泛型扩展方法
2) 它和select()一样作用与IEnumerable<TSource>类型
3) 它只接收一个Func<TSource,Tkey>类型参数,在这里keySelctor指定要排序的字段。
4) 如果想要降序排列可以使用orderbyDescending方法。
(2) 举例说明,同上例,实现排序的代码如下:
//var result = persons.OrderBy(p => p);
//按照名字的最后一个字母排序
//var result = persons.OrderBy(p => p.Substring(p.Length – 1, 1)).Select(p => p);
//降序排列
var result = persons.OrderByDescending(p => p);
result.Print();
- Linq基本查询操作符-分组数据
(1) GroupBy() 语法是:
public static IEnumerable<IGrouping<Tkey,TSource>>
GroupBy<TSource,TKey>(
this IEnumerable<TSource> source,
Func<TSource,TKey> keySelector )
说明:1) GroupBy()方式和OrderBy()方式非常类似,它也是一个泛型扩展方法。
2) 它和OrderBy()一样作用与IEnumerable<TSource>类型。
3) 它只接受一个Func<TSource,TKey>类型参数,在这里keySelector指定要分组的字段。
(2) 举例说明,同上例,实现分组的代码是:
//分组—按照姓名来分组¦–取出姓名中的空格前的部分
var result = persons.GroupBy(p => p.Split(new char[] { ‘ ‘ })[0]);
foreach (var group in result)
{
Console.WriteLine(“姓:” + group.Key);
foreach (var name in group)
{
Console.WriteLine(“\t” + name);
}
Console.WriteLine();
}
- 查询执行的时机
(1) 从前面的试验中,我们发现一次查询实际上经过以下3步。
1) 第一步:获取数据源 int[] numbers=new int[]{3,45,65,76,2,434,54,65,76,76,65,43};
2) 第二步:定义查询 var even=numbers.Where(p=>p%2==0).Select(p=>{
Console.WriteLine(“Hi!”+p.ToString());
return p; });
3) 第三步:执行查询 foreach(var item in even){ }
- 查询执行的时机小节
(1) 查询分为以下三步,获取数据源,定义查询,执行查询
(2) 定义查询后,查询直到需要枚举结果时才被真正执行,这种方法称为”延迟执行”。
(3) 当查询结果返回单一值时,查询立即执行。举例,如代码:
//查询时机—当返回值为单值时马上执行语句,负责延迟执行
var result = persons.Select(p => p).Count();
Console.WriteLine(“个数是” + result);
(4) 因此,可以通过以下技巧在定义查询时就强制执行查询
- Linq查询的两种方式
(1) Method syntax,查询方法方式
主要利用System.Linq.Enumerable类中定义的扩展方法和Lambda表达式方式进行查询。
(2) Query syntax ,查询语句方式
- 查询语句VS查询方法
注:查询语句和查询方法存在着紧密的关系
(1) CLR本身并不理解查询语句,它只理解查询方法。
(2) 编译器负责在编译时将查询语句翻译为查询方法。
(3) 大部分查询方法都有对应的查询语句形式,如:Select()对应select,OrderBy()对应orderby。
(4)部分查询方法目前在C#中还没有对应的查询语句:如:Count()和Max()这时只能采用以下替代方案
1) 查询方法
2) 查询语句+查询方法的混合方式
(5) 一般情况下,建议使用可读性更好的查询语句。举例说明:
还是用上面多定义的泛型集合数组persons,用查询语句实现几个简单的功能,代码如下:
//输出persons中的所有的元素
var result = from p in persons select p;
//输出persons中姓zhang的人—-语句和方法的混合编排?
var result = (from p in persons select p).Where(p => p.StartsWith(“zhang”));
//排序
var result = from p in persons orderby p select p;
result.Print();
- 高级查询方法
(1) 聚合类 Count(),Max()/Min(),Average(),Sum()。举例说明:
重新定义一个数组来实现上面的各种各样的方法,代码如下:
//LINQ to Objects查询高级方法
//数组数据arr
int[] arr = { 23, 34, 5, 5, 23, 45, 65, 33, 43, 76, 67, 87 };
//聚合类
Console.WriteLine(“arr的最大值: + arr.Max());
Console.WriteLine(“arr的最小值¦: ” + arr.Min());
Console.WriteLine(“arr的平均值¦: ” + arr.Average());
Console.WriteLine(“arr的数组元素个是” + arr.Count());
Console.WriteLine(“arr的总和是: ” + arr.Sum());
(2) 排序类 thenBy() 代码如下:
//排序类
var result = arr.OrderBy(p => p.ToString().Substring(0, 1));
//2次排序混编模式没有达到要求
var result = arr.OrderBy(p => p.ToString().Substring(0, 1)).ThenBy(p => p);
//按照语句排序
var t = arr.OrderBy(p => p.ToString().Substring(0, 1));
var result = from p in t orderby p descending select p;
(3) 分区类 Take,TakeWhile,Skip,SkipWhile 代码如下:
//分区类
var result = arr.Skip(3).Take(3); //跳过三个值取三个值
var result = arr.Skip(3); //跳过几个值
var result = arr.SkipWhile(p => p > 4); //方法体部分是该Linq语句不在往后执行的条件,当第一次遇到条件成立时,取剩下的所有元素
var result = arr.TakeWhile(p => p > 4); //方法体部分是该Linq语句提取数据的条件,当第一次遇到条件不成立的情况就停止执行
(4) 集合类 Distinct 代码如下:
//集合类
var result = arr.Distinct();
(5) 生成类 Range,Repeat 代码如下:
//生成类—–静态类
var result = System.Linq.Enumerable.Range(10, 50);
var result = System.Linq.Enumerable.Range(‘a’, 50); //生成连续的序列
var result = System.Linq.Enumerable.Repeat(40, 10);
result.Print();
- 生成类查询方法小结
注:使用生成类查询方法时,需要注意以下几点:
(1) 和其它几类方法不同,Range/Repeat不是扩展方法,而是普通的静态方法
(2) Range只能产生整数序列。
(3) Repeat可以产生泛型序列。
(4) 所有的查询方法都存放在System.Linq.Enumerable静态类中。