1.var推断类型
只能定义局部变量,不能定义成员变量
定义的时候必须同时完成初始化,不能使用var定义变量为null
var本身不是一个新类型,只是用来修饰可以推断出具体类型的局部变量
从IL编译的角度来讲,没有任何区别
2.匿名类
直接使用new关键字创建对象,使用var定义对象属性
而不需要提前编写类的成员,并且只能添加对象的属性
1 var objPerson=new
2 {
3 Name="小王",
4 Age=25,
5 ClassName="软件1班"
6 };
3.扩展方法
扩展方法必须在静态类中定义
扩展方法是静态方法
类本身的方法与扩展方法重名时,类本身的方法被优先使用
第一个参数前加关键字this,this后的类型表示为所有的此种类型添加扩展方法4
扩展方法内如果只有一个参数,它不是参数,代表当前变量
扩展方法也可以重载
扩展方法不要过多使用
4.扩展方法的应用
如果想为一个封装好的密封类添加一个方法,可以用扩展方法
5.扩展方法的定义
不带参数的扩展方法: static 方法名 (this 目标类型 目标类型参数)
带参数的扩展方法定义: static 方法名 (this 目标类型 目标类型参数, 参数类型1 参数名1,,...... )
1 public static int GetAvg(this int sum)
2 {
3 return sum / 5;
4 }
5
6 public static string StuInfo(this string name)
7 {
8 return string.Format("{0}你好,你的5门平均成绩为:", name);
9 }
10
11 public static string WelcomeStu(this Student stu)
12 {
13 return "欢迎你:" + stu.StuName;
14 }
15
16 public static string WelcomeStu(this Student stu,int age)
17 {
18 return string.Format("姓名{0},年龄{1}", stu.StuName,age);
19 }
6.委托
委托可以看成是一种数据类型,可用于定义变量,但它是一种特殊的变量。
委托定义的变量能接受的数值只能是一个方法(函数),可以理解委托就是一个方法的指针。
7.委托使用的步骤
7.1声明委托,一般声明在类的外部
7.2根据委托定义的函数原型编写需要的方法(可能多个方法)
7.3实例化委托对象,委托在使用前必须实例化,实例化时需指定一个默认的方法
7.4通过委托调用方法,而不是直接调用方法
7.5委托对象所关联的方法可以动态变化(+=、-=)
1 //【1】声明委托(定义一个函数的原型:返回值 + 参数类型和个数)
2 //一般定义在类的外部
3 public delegate int CalculatorDelegate(int a, int b);
4 //【2】根据委托定义一个“具体方法”实现加法功能
5 static int Add(int a, int b)
6 {
7 return a + b;
8 }
9 //【2】根据委托定义一个“具体方法”实现减法功能
10 static int Sub(int a, int b)
11 {
12 return a - b;
13 }
14 static void Main(string[] args)
15 {
16 //【3】创建委托对象,关联“具体方法”
17 CalculatorDelegate objCal = new CalculatorDelegate(Add);
18 //【4】通过委托去调用方法,而不是直接使用方法
19 int result = objCal(10, 20);
20 Console.WriteLine("10+20={0}", result);
21
22 objCal -= Add; //断开当前委托对象所关联的方法(加法)
23 objCal += Sub; //重新指向一个新的方法(减法)
24
25 result = objCal(10, 20); //重新使用委托对象,完成减法功能
26 Console.WriteLine("10-20={0}", result);
27 Console.ReadLine();
28 }
8.匿名方法
没有具体名称、而只有委托关键字、方法参数、方法体,所以称之为匿名方法。
1 static void Main(string[] args)
2 {
3 //委托变量接收一个匿名方法
4 CalculatorDelegate objCal = delegate(int a, int b)
5 {
6 return a + b;
7 };
8 int result = objCal(10, 20);
9 Console.WriteLine("10+20={0}", result);
10 Console.ReadLine();
11 }
9.Lambda表达式
(参数列表) => {方法体} goes to
参数列表中的参数类型可以是“明确”的或Var的
如果是Var的,则参数的数据类型将由编译器根据上下文自动推断出来
1 static void Main(string[] args)
2 {
3 //委托变量接收一个Lambda表达式
4 CalculatorDelegate objCal = (int a, int b) => { return a + b; };
5 int result = objCal(10, 20);
6 Console.WriteLine("10+20={0}", result);
7 Console.ReadLine();
8 }
9
10 static void Main(string[] args)
11 {
12 MathDelegate objMath = a => a * a;
13 int result = objMath(10);
14 Console.WriteLine("a的平方={0}", result);
15 Console.ReadLine();
16 }
如果参数只有一个可以省略();如果方法体只有一行代码可以省略{}
10.LINQ,语言集成查询
10.1 LINQ to Objects 主要负责对象的查询
10.2 LINQ to XML 主要负责XML的查询
10.3 LINQ to ADO.NET 主要负责数据库的查
10.3.1 LINQ to SQL :目前已没人使用
10.3.2 LINQ to DataSet :应用一般
10.3.3 LINQ to Entiies : 重点学习
1 static void Main(string[] args)
2 {
3 int[] nums = { 1, 7, 2, 6, 5, 4, 9, 13, 20 };
4 List<int> list = new List<int>();
5 foreach (int item in nums)
6 {
7 if (item % 2 != 0)
8 list.Add(item);
9 }
10 list.Sort();
11 list.Reverse();
12 foreach (int item in list)
13 {
14 Console.WriteLine(item);
15 }
16 Console.ReadLine();
17 }
1 static void Main(string[] args)
2 {
3 int[] nums = { 1, 7, 2, 6, 5, 4, 9, 13, 20 };
4
5 //查询数组中的奇数并按降序排列输出
6 var list = from num in nums
7 where num % 2 != 0
8 orderby num descending
9 select num;
10
11 foreach (int item in list)
12 {
13 Console.WriteLine(item);
14 }
15 Console.ReadLine();
16 }
11.LINQ中的Select()方法
Select()是一个泛型扩展方法
Select()方法使用的时候,要求传递一个委托实例
数组、泛型集合都可以使用扩展方法Select()
1 static void Main(string[] args)
2 {
3 int[] nums = { 1, 7, 2, 6, 5, 4, 9, 13, 20 };
4
5 //返回数组中每个数值的平方
6 //Select()方法里面是一个Lambda表达式
7 //返回结果是一个迭代器(Iterator)
8 var list = nums.Select(item => item * item);
9 foreach (int item in list)
10 {
11 Console.WriteLine(item);
12 }
13
14 Console.ReadLine();
15 }
迭代器就是一个类似于数组和泛型集合可以遍历的东西
12.LINQ中的Where()方法
Where()方法是一个泛型扩展方法
Where()方法使用的时候要求传递一个委托实例,该实例是一个判断条件,返回的类型必须是bool类型
1 static void Main(string[] args)
2 {
3 int[] nums = { 1, 7, 2, 6, 5, 4, 9, 13, 20 };
4
5 //先对数组内的数值进行判断,保留偶数
6 //对是偶数的源数据进行平方
7 var list = nums
8 .Where(item => item % 2 == 0)
9 .Select(i => i * i);
10
11 Console.ReadLine();
12 }
13.LINQ中的OrderBy()方法
OrderBy()方法是一个泛型扩展方法
OrderBy()里面的参数要求传递一个排序的字段,如果字段是int,参数可以是(item=>item),如果想按照字符串的首字母排序可以是(item=>item.Substring(0,1))
升序排列(从小到大)可以用OrderBy()方法
降序排列(从大到小)可以用OrderByDescending()方法
1 static void Main(string[] args)
2 {
3 int[] nums = { 1, 7, 2, 6, 5, 4, 9, 13, 20 };
4
5 //1.先提取偶数
6 //2.对是偶数的进行平凡
7 //3.对平凡后的数值进行排序(升序)
8 var list = nums
9 .Where(item => item % 2 == 0)
10 .Select(i => i * i)
11 .OrderBy(item => item);
12 foreach (int i in list)
13 {
14 Console.WriteLine(i);
15 }
16
17 Console.ReadLine();
18 }
1 static void Main(string[] args)
2 {
3 string[] nums = { "张勇", "王琦", "刘静", "赵鑫鑫",
4 "杜丽", "马俊才", "那英", "成龙", };
5
6 //1.先提取出名字是两个字的
7 //2.按名字首字母进行降序(Z—>A)排列
8 var list = nums
9 .Where(item => item.Length == 2)
10 .Select(item => item)
11 .OrderByDescending(item => item.Substring(0, 1));
12 foreach (string item in list)
13 {
14 Console.WriteLine(item);
15 }
16
17 Console.ReadLine();
18 }
14.LINQ中的GroupBy()方法
GroupBy()方法是一个泛型扩展方法
GroupBy()里面的参数要求传递一个f分组的字段
1 static void Main(string[] args)
2 {
3 string[] nums = { "张勇", "王琦", "刘静", "赵鑫鑫","杜丽",
4 "马俊才", "那英", "成龙","王丽", "杜宇","马晓","刘丽","马大哈",};
5
6 //1.先提取两个字的名字
7 //2.按姓进行分组
8 var list = nums
9 .Where(item => item.Length == 2)
10 .Select(item => item)
11 .GroupBy(item => item.Substring(0, 1));
12
13 foreach (var groupItem in list)
14 {
15 Console.WriteLine("-------------------");
16 Console.WriteLine("分组字段:{0}", groupItem.Key);
17
18 foreach (var item in groupItem)
19 {
20 Console.WriteLine(item);
21 }
22 }
23 Console.ReadLine();
24 }
15.LINQ查询的时机:延迟执行
定义查询后,查询并没有立即执行,而是直到需要枚举结果(遍历)时才真正被执行
顺序:获取数据源、定义查询、执行查询(不使用不执行)
16.Count()方法
使用“聚合扩展方法”返回单一结果,强制查询立即执行。后加.Count(),查询定义后会立即执行
17.LINQ查询的两种形式:查询语句、查询方法
查询语句比较接近于SQL语句查询,可读性更好,但查询语句最后还是要被翻译成查询方法。
查询方法利用System.Linq.Enumerble类中的扩展方法和Lambda表达式进行查询。
1 static void Main(string[] args)
2 {
3 int[] nums = { 1, 7, 2, 6, 5, 4, 9, 13, 20 };
4
5 var list = nums
6 .Where(item => item % 2 == 0)
7 .Select(i => i * i)
8 .OrderByDescending(i => i);
9
10 foreach (var item in list)
11 {
12 Console.WriteLine(item);
13 }
14
15 Console.ReadLine();
16 }
17
18 //两者的执行效果完全一样
19
20 static void Main(string[] args)
21 {
22 int[] nums = { 1, 7, 2, 6, 5, 4, 9, 13, 20 };
23
24 var list = from num in nums
25 where num % 2 == 0
26 orderby num descending
27 select num * num;
28
29 foreach (var item in list)
30 {
31 Console.WriteLine(item);
32 }
33
34 Console.ReadLine();
35 }
我个人觉得直接用查询方法好一些,可以多多使用Lambda表达式。
个人杂记:最近每次遇到“求”字,内心都起波澜,想起中学一篇文章叫《送东阳马生序》,是文人宋濂讲述自己年少求学时的经历。细想人这一生,年少求学,毕业求职,成年求偶,婚后求子,中年求财,老年求后,真可谓不得不积极入世,一心相求。其中经历虽若坎坷艰难,但仔细思考,人生就是因为追求而精彩,生命正是因为拼搏而有意义,每一次的追求与拼搏都是跨过人生的一道道坎,过去了方能精彩无限,犹如登上山峦一览众山小的壮阔,仿佛临海朝平两岸阔的凯旋。
18.LINQ查询子句
查询表达式
是一种查询语法表示的表达式,由一组类似于SQL的语法编写的句子组成
每一个子句可以包含一个或多个C#表达式
LINQ查询表达式必须以from子句开头,并且必须以select或group子句结束,中间可以添加别的子句
LINQ查询表达式包含的子句
from子句:指定查询操作的数据源和范围变量
where子句:筛选元素的逻辑条件,返回值是一个bool类型
select子句:指定查询结果的类型和变现形式
orderby子句:对查询结果进行排序(升序或降序)
group子句:对查询结果进行分组
into子句:提供一个临时标识符,该表示可充当join/group/select子句结果的引用
join子句:连接多个查询操作的数据源
let子句:引入用于存储查询表达式中的子表达式的范围变量
19.from子句
LINQ查询表达式必须包含from子句,并且必须以from子句开头
from子句指定的数据源必须为IEnumerable、Ienumerable<T>或者两者的派生类型(例如:数组、List<T>、ArrayList等)
from num in nums :num表示范围变量:一般表示数据源中的每一个元素
nums表示数据源
20.复合from子句查询
如果数据源的元素还包括字数据源,如果要查询字数据源中的元素,则需要使用复合from子句。
1 static void Main(string[] args)
2 {
3 Student obj1 = new Student()
4 {
5 StuId = 1001, StuName = "学员1", ScoreList = new List<int>() { 90, 78, 54 }
6 };
7 Student obj2 = new Student()
8 {
9 StuId = 1002, StuName = "学员2", ScoreList = new List<int>() { 95, 88, 90 }
10 };
11 Student obj3 = new Student()
12 {
13 StuId = 1003, StuName = "学员3", ScoreList = new List<int>() { 79, 76, 89 }
14 };
15 //将学员封装到集合中
16 List<Student> stuList = new List<Student>() { obj1, obj2, obj3 };
17 //查询成绩包含95分以上的学员
18 var result = from stu in stuList
19 from score in stu.ScoreList
20 where score >= 95
21 select stu;
22 //显示查询结果
23 foreach (var item in result)
24 {
25 Console.WriteLine(item.StuName);
26 }
27 Console.ReadLine();
28 }
21.多个from子句查询
若LINQ查询表达式包含两个或两个以上的独立数据源时,可以使用多个from子句查询所有数据源中的数据
1 static void Main(string[] args)
2 {
3 Student obj1 = new Student() { StuId = 1001, StuName = "学员1" };
4 Student obj2 = new Student() { StuId = 1009, StuName = "学员9" };
5 Student obj3 = new Student() { StuId = 1012, StuName = "学员12" };
6 Student obj4 = new Student() { StuId = 1003, StuName = "学员3" };
7 Student obj5 = new Student() { StuId = 1019, StuName = "学员19" };
8 Student obj6 = new Student() { StuId = 1006, StuName = "学员6" };
9
10 List<Student> stuList1 = new List<Student>() { obj1, obj2, obj3 };
11 List<Student> stuList2 = new List<Student>() { obj4, obj5, obj6 };
12
13 //查询学好大于1010的学员
14 var result = from stu1 in stuList1
15 where stu1.StuId >= 1010
16 from stu2 in stuList2
17 where stu2.StuId >= 1010
18 elect new { stu1, stu2 };
19 //显示查询结果
20 foreach (var item in result)
21 {
22 Console.WriteLine(item.stu1.StuName + " " + item.stu1.StuId);
23 Console.WriteLine(item.stu2.StuName + " " + item.stu2.StuId);
24 }
25 Console.ReadLine();
26 }
22.其他常用子句
where子句
用于指定筛选元素的逻辑条件
一个查询表达式可以不包含where子句
如果查询表达式包含where子句,则where子句不能放在最后一个子句
select子句
用于指定查询结果的类型和表现形式
LINQ查询表达式或以select子句结尾或以group子句结尾
group子句
用于对查询结果分组
返回元素类型为Igrouping<Tkey,Telement>对象序列
orderby子句
用于对查询结果排序,默认“升序”
在排序字段后加上descending可以表示降序
23.高级查询方法
聚合类:Count Max/Min Average
排序类:ThenBy
分区类:Take TakeWhile Skip SkipWhile
集合类:Distinct
生成类:Range Repeat
24.Count 返回集合项的数目
Max/Min Average 最大最小及平均
1 static void Main(string[] args)
2 {
3 Student obj1 = new Student() { StuId = 1001, StuName = "学员1" };
4 Student obj2 = new Student() { StuId = 1009, StuName = "学员9" };
5 Student obj3 = new Student() { StuId = 1012, StuName = "学员12" };
6 Student obj4 = new Student() { StuId = 1003, StuName = "学员3" };
7 Student obj5 = new Student() { StuId = 1019, StuName = "学员19" };
8 Student obj6 = new Student() { StuId = 1006, StuName = "学员6" };
9 List<Student> stuList = new List<Student>() { obj1, obj2, obj3, obj4, obj5, obj6 };
10
11 var count1 = (from c in stuList
12 where c.StuId > 1010
13 select c).Count();
14 var count2 = stuList.Where(c => c.StuId > 1010).Count();
15 Console.WriteLine("count1={0} count2={1}", count1, count2);
16 Console.ReadLine();
17 }
1 static void Main(string[] args)
2 {
3 Student obj1 = new Student() { StuId = 1001, Age = 22, StuName = "学员1" };
4 Student obj2 = new Student() { StuId = 1009, Age = 21, StuName = "学员9" };
5 Student obj3 = new Student() { StuId = 1012, Age = 25, StuName = "学员12" };
6 Student obj4 = new Student() { StuId = 1003, Age = 23, StuName = "学员3" };
7 Student obj5 = new Student() { StuId = 1019, Age = 27, StuName = "学员19" };
8 Student obj6 = new Student() { StuId = 1006, Age = 24, StuName = "学员6" };
9 List<Student> stuList = new List<Student>() { obj1, obj2, obj3, obj4, obj5, obj6 };
10
11 var maxAge = (from s in stuList select s.Age).Max();
12 var minAge = stuList.Select(s => s.Age).Min();
13 var avgAge = (from s in stuList select s.Age).Average();
14 var sumAge = (from s in stuList select s.Age).Sum();
15
16 Console.WriteLine("maxAge={0} minAge={1} avgAge={2} sumAge={3}",
17 maxAge, minAge, avgAge, sumAge);
18
19 Console.ReadLine();
20 }
25.ThenBy提供符合排序条件
1 static void Main(string[] args)
2 {
3 Student obj1 = new Student() { StuId = 1001, Age = 22, StuName = "学员1" };
4 Student obj2 = new Student() { StuId = 1009, Age = 21, StuName = "学员9" };
5 Student obj3 = new Student() { StuId = 1012, Age = 25, StuName = "学员12" };
6 Student obj4 = new Student() { StuId = 1003, Age = 23, StuName = "学员3" };
7 Student obj5 = new Student() { StuId = 1019, Age = 27, StuName = "学员19" };
8 Student obj6 = new Student() { StuId = 1006, Age = 24, StuName = "学员6" };
9 List<Student> stuList = new List<Student>() { obj1, obj2, obj3, obj4, obj5, obj6 };
10 var stus1 = from s in stuList
11 orderby s.StuName, s.Age, s.StuId
12 select s;
13 var stus2 = stuList
14 .OrderBy(s => s.StuName)
15 .ThenBy(s => s.Age)
16 .ThenBy(s => s.StuId)
17 .Select(p => p);
18 foreach (var s in stus1)
19 {
20 Console.WriteLine(s.StuName);
21 }
22 Console.WriteLine("----------------------");
23 foreach (var s in stus2)
24 {
25 Console.WriteLine(s.StuName);
26 }
27 Console.ReadLine();
28 }
26.Take 提取指定数量的项
Skip 跳过指定数量的项并获取剩余的项
TakeWhile 只要满足指定的条件,就会返回序列的元素,然后跳过剩余的元素
SkipWhile 只要满足指定的条件,就跳过序列中的元素,然后返回剩余元素
1 static void Main(string[] args)
2 {
3 int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
4
5 var list1 = nums.Skip(1);
6 var list2 = nums.Skip(1).Take(3);
7 var list3 = nums.SkipWhile(i => i % 3 != 0);
8 var list4 = nums.TakeWhile(i => i % 2 != 0);
9 var list5 = nums.SkipWhile(i => i % 3 != 0)
10 .TakeWhile(i => i % 2 != 0);
11
12 foreach (var item in list1) { Console.Write(item + " "); }
13 Console.WriteLine("\n---------------------");
14 foreach (var item in list2) { Console.Write(item + " "); }
15 Console.WriteLine("\n---------------------");
16 foreach (var item in list3) { Console.Write(item + " "); }
17 Console.WriteLine("\n---------------------");
18 foreach (var item in list4) { Console.Write(item + " "); }
19 Console.WriteLine("\n---------------------");
20 foreach (var item in list5) { Console.Write(item + " "); }
21
22 Console.ReadLine();
23 }
27.Range 生成一个整数序列
Repeat 生成一个重复项的序列
Rang/Repeat不是扩展方法,而是普通的静态方法
Rang只能产生证书序列
Repeat可以产生泛型序列
所有的查询方法都存放在System.Linq.Enumerable静态类中
1 static void Main(string[] args)
2 {
3 var nums1 = Enumerable.Range(1, 10);
4 var nums2 = Enumerable.Repeat("LINQ best!", 10);
5
6 foreach (var item in nums1) { Console.WriteLine(item); }
7 Console.WriteLine("------------");
8 foreach (var item in nums2) { Console.WriteLine(item); }
9
10 Console.ReadLine();
11 }
28.Distinct 去除重复的元素
1 static void Main(string[] args)
2 {
3 int[] nums = { 1, 2, 2, 6, 5, 6, 7, 8, 8 };
4 var list = nums.Distinct();
5
6 foreach (var item in list) { Console.WriteLine(item); }
7
8 Console.ReadLine();
9 }