C#学习笔记(十四) LINQ

第十九章 LINQ

  1. LINQ:语言集成查询(Language Intergrated Query)。它允许我们以SQL查询数据库的方式查询数据集合,使用它可以从数据库、程序对象集合和XML中查询数据。
  2. 匿名类型:通俗的说,匿名类型就是在对象初始化时不提供类型,在LINQ中会经常用到,如var students = new {name = "automation",age = 16};
  3. 匿名类型只能和局部变量一块使用,不能作为类成员;由于匿名类型没有名字,需使用关键字var作为变量类型;不能设置匿名类型对象的属性,为匿名类型创建的属性是只读的。
  4. 匿名类型的成员有三种形式,赋值形式,成员访问表达式以及标识符,如果是后两种,就需要提前确定好它们的量。var students = new {name = "automation",age = Person.Age,Major};其中,Person.Age和Major需要提前定义好才可以。
  5. LINQ的两种语法形式:方法语法和查询语法,查询语法通俗易懂,方法语法是一组标准查询运算符的方法。查询语法是声明式的,它描述你想要返回的东西,但没有指明如何执行这个查询;方法语法是命令式的指明查询方法调用的顺序。
  6. 示例:
using System;
using System.Linq;
using System.Xml.Linq;

namespace test42
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] number = {15,16,18,36,56,81,100};
            var numb1 = from num in number		//给出数据源number
                        where num >= 18		//条件判断
                        select num;		//选择元素
            var numb2 = number.Where(num => num % 3 == 0);  		//Lambda表达式,方法语法
            int count = number.Count();		//方法语法
            foreach(var nu1 in numb1)
            {
                Console.WriteLine("nu1:{0}",nu1);
            }   
             foreach(var nu2 in numb2)
            {
                Console.WriteLine("nu2:{0}",nu2);
            }       
            Console.WriteLine("numb2的个数:{0}",count);
        }
    }
}

执行结果:

在这里插入图片描述

  1. 如果查询表达式返回的是枚举类型,知道处理枚举时才会执行,并且查询多少次枚举就会执行多少次,如果在执行查询之前枚举值有变化,会返回变化后的值,如果返回标量值,则查询会立即执行,并将结果保存在查询变量中。
  2. from子句:指定作为数据源的数据集合,引入迭代变量,来表示数据源的每一数据。语法格式为from Type item in Items其中,类型Type是可选的,item是迭代变量名,Items是要查询的集合名称,必须是可枚举的。from子句可以有任意多个,通常会与foreach()语句配合使用。
  3. join子句:将两个或多个数据进行结合;联结操作接受两个数据源,然后创建一个新的对象集合,集合中的元素包含原始数据源的所有字段。语法格式为join Identifier in Collection on Filed1 equals Filed2它是将多个集合中的元素符合条件的都筛选出来。
  4. join子句示例:
using System;
using System.Linq;
using System.Xml.Linq;

namespace test43
{
    class Myclass1
    {
        public int[] num1 = {15,18,32,36,81,56,94};
    }
    class Myclass2
    {
        public int[] num2 = {12,16,25,36,45,21,75,81};
    }
    class Program
    {
        static void Main(string[] args)
        {
           Myclass1 mycl1 = new Myclass1();
           Myclass2 mycl2 = new Myclass2();
           var num = from mycll1 in mycl1.num1
                     join mycll2 in mycl2.num2 on mycll1 equals mycll2
                     into number		//查询延续,将满足条件的mucll2加入新的集合number中
                     from numb in number
                     select numb;		//以select语句结尾
            foreach(var nub in num)
            {
                Console.WriteLine(nub);
            }         
        }
    }
}

执行结果是:36和81。

  1. let子句:接受一个表达式运算并将其赋值给一个变量,而这个变量又可以在接下来的语句中使用。示例:
using System;
using System.Linq;
using System.Xml.Linq;

namespace test43
{
    class Myclass1
    {
        public int[] num1 = {15,18};
    }
    class Myclass2
    {
        public int[] num2 = {12,16,25};
    }
    class Program
    {
        static void Main(string[] args)
        {
           Myclass1 mycl1 = new Myclass1();
           Myclass2 mycl2 = new Myclass2();
           var num = from mycll1 in mycl1.num1		//给出数据源
                     from mycll2 in mycl2.num2
                     let number = mycll1 + mycll2		//let子句接受一个表达式
                     where number>=31
                     select new {mycll1,mycll2,number};		//select子句可以是一个数据项或者匿名类型
            foreach(var nub in num)		//显示结果
            {
                Console.WriteLine(nub);
            }         
        }
    }
}

执行结果:

在这里插入图片描述

  1. orderby子句: 就是对元素进行排序,默认是升序(ascending),也可以降序(descending)。示例:
using System;
using System.Xml.Linq;
using System.Linq;

namespace test44
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] number = {15,16,85,56,42,36,69};
            var num = from numb in number
                      orderby numb      //对元素排序
                      select numb;
            foreach(var numb in num)
            {
                Console.Write("{0} ",numb);
            }                     
        }
    }
}

执行结果:

在这里插入图片描述

  1. group…by子句:将select的对象按照一定的标准进行分组;如果项包含在查询结果中,他们可以根据某个字段的值分组,作为分组依据的属性叫键;group子句返回的不是原始数据项的枚举,而是项的分组的可枚举类型;分组本身是可枚举类型,可以枚举实际的项。
using System;
using System.Xml.Linq;
using System.Linq;

namespace test44
{
    class Program
    {
        static void Main(string[] args)
        {
           var students = new[]
           {
              new {LName = "Kang",FName = "xiaoqiu",Age = 18,Major = "History"} ,
              new {LName = "zhang",FName = "goddess",Age = 18,Major = "English"} ,
              new {LName = "wei",FName = "Angel",Age = 18,Major = "History"} 
           };
           var query = from stu in students
                       group stu by stu.Major;    
            foreach(var s in query)
            {
                Console.WriteLine("{0}",s.Key);
                foreach(var v in s)
                {
                    Console.WriteLine("     {0} {1}",v.LName,v.FName);
                }
            }            
        }
    }
}

执行结果:

在这里插入图片描述

  1. 标准查询运算符:被查询的集合对象叫做序列,它必须实现IEnumerable接口;标准查询运算符使用方法语法,一共有47种;有些运算符返回可枚举类型,有些返回标量,返回标量的运算符会立即执行,并返回一个值;很多操作以谓词作为参数,谓词是一个方法,它以对象作为参数,根据对象是否满足条件返回true或false。
  2. 标准查询运算符的签名:System.Linq.Enumerable类声明了标准查询运算符方法,但这些方法不仅仅是一些方法,它们是扩展了IEnumerable泛型类的扩展方法。比如Count、First和Where方法签名如下,必须声明为public static形式Count方法返回序列中的所有元素个数,First方法返回序列中的第一个元素。
public ststic int Count<T>(this IEnumerable<T>  source);
public ststic T First<T>(this IEnumerable<T>  source);
public ststic  IEnumerable<T> Where<T>(this IEnumerable<T>  source,...);
int[] number = new int[]{12,16,18,21,25,36,45,56,81};
var countnum1 = Enumerable.Count(number);
var firstnum1 = Enumerable.First(number);		//方法语法
var countnum2 = number.Count();
var firstnum2 = number.First();		//扩展方法
  1. 结合查询语句和方法语句:可以将查询语句作为一个整体运用在方法语句中。
var numbers = new {12,16,18,21,25,36,45,56,81};
var number = (from num in numbers
			  where num %3 == 0
			  select num).Count();
Console.WriteLine("The number can be divided by three: ");					  
foreach(var n in number)
{			  
	Console.WriteLine("{0}",n);		
}	  					
  1. 将委托作为参数:将委托作为标准查询运算符的参数,可以为方法增加额外的功能,因为委托总是持有方法的。比如Count方法
public static int Count<T>(this IEnumerable<T>,Func<T,bool> func);

让Count方法统计能够被3整除的数

int[] numbers = new int[]{12,16,18,21,25,36,45,56,81};
int divnum = numbers.Count(x => x%3==0);		//寻找整除3的Lambda表达式
  1. LINQ预定义的委托类型:有两种,Func委托和Action委托,各有17个成员,TR代表返回值,必须是类型参数列表的最后一项,Func委托的前四项为
public delegate TR Func<out TR>();		//没有方法参数
public delegate TR Func<in T1,out TR>(T1 a1);
public delegate TR Func<in T1,in T2,out TR>(T1 a1,T2 a2);
public delegate TR Func<in T1,in T2,in T3,out TR>(T1 a1,T2 a2,T3 a3);

Action委托的前四项没有返回值,也就没有返回值的类型参数,它们为

public delegate void Action ();
public delegate void Action<in T1>(T1 a1);
public delegate void Action<in T1,in T2>(T1 a1,T2 a2);
public delegate void Action<in T1,in T2,in T3>(T1 a1,T2 a2,T3 a3);

19.使用委托参数示例:

class Program
{
	static bool IsOdd(int x)		//委托对象持有的方法
	{
		return x%2 = =1;
	}
	static void Main()
	{
		int[] intArray = new int[]{16,15,25,36,48,63};
		Func<int,bool> mydel = new Func<int,bool>(IsOdd);		//创建委托对象
		var countodd = intArray.Count(mydel);		//执行委托
		Console.WriteLine("Count of odd numbers:{0}",countodd);
	}
}
  1. 使用Lambda表达式参数的示例:
class Program
{
	static void Main()
	{
		int[] intArray = new int[]{16,15,25,36,48,63};
		var countodd = intArray.Count(x => x%2==1);
		Console.WriteLine("Count of odd numbers:{0}",countodd);
	}
}

也可以使用匿名方法代替Lambda表达式,但是显得复杂些

class Program
{
	static void Main()
	{
		int[] intArray = new int[]{16,15,25,36,48,63};
		Func<int,bool> mydel = delegate(int x)
							   {
									return x%2 == 1;			
							   };
		var countodd = intArray.Count(mydel);
		Console.WriteLine("Count of odd numbers:{0}",countodd);
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值