static void Main(string[] args) { #region 【1】使用 var 推断类型 var a = 20; var bookName = ".NET开发"; var student1 = new Student() { StudentName = "Damon Salvatore", Age = 22 }; Console.WriteLine($"【1】var关键字的使用:共有 {a} 个人在学习{bookName} 系列课程,其中{student1.StudentName} ,{student1.Age}岁,已经是高手了。"); //Var在匿名类中的使用(后面学习EF的时候,会大量使用) var person = new { Name = "Damon", Age = 25, ClassName = "计算机一班" }; Console.WriteLine("【4】var在匿名类中的使用-->姓名:{0} 年龄:{1} 班级:{2}", person.Name, person.Age, person.ClassName); #endregion #region 【2】委托基础 Console.WriteLine("\r\n------------------委托基础使用-------------------"); //委托的基本概念:委托其实就是一个方法的原型:返回值 + 参数类型和个数 //委托:方法的指针(方法的代表) //2.3 创建委托对象(关联具体的方法) CalculatorDelegate delCal = new CalculatorDelegate(Add); // CalculatorDelegate delCal1 = Add //2.4 通过委托调用方法,而不是直接使用方法 delCal(50, 20); //2.5 多路委托(多播委托) Console.WriteLine("------------------------------------------"); delCal += Sub; // delCal(50, 20); Console.WriteLine("------------------------------------------"); delCal += Mul; delCal(50, 20); Console.WriteLine("------------------------------------------"); delCal -= Add; delCal -= Sub; delCal(50, 20); #endregion #region 【3】匿名方法 Console.WriteLine("\r\n-----------------匿名方法的使用------------------"); /* 这个方法没有具体的名称,只有委托关键字,方法的参数,方法体,所以称为匿名方法 * 匿名方法的使用:匿名方法允许委托变量作为参数传递,以代替单独方法的定义 */ CalculatorDelegate delCal2 = delegate(int num1, int num2) { Console.WriteLine("通过匿名方法计算:a+b={0}", num1 + num2); }; delCal2(100, 50); #endregion #region 【4】Lambda 表达式 Console.WriteLine("\r\n-----------------Lambda表达式的使用------------------"); /* C#3.0时代,引入了Lambda表达式,利用他可以更加简练的编写代码块 * Lambda表达式中的参数类型可以是“明确类型”,也可以是“推断类型” * 如果是推断类型,则参数的数据类型是编译器根据上下文自动推断出来。 * Lambda表达式与匿名方法比较: * lambda表达式本身就是匿名方法。 * Lambda表达式参数允许不明确声明,而匿名方法参数类型必须明确指出。 * Lambda 表达式中方法体,允许单一表达式或者多条语句组成,而匿名方法不允许单一表达式。 */ CalculatorDelegate delCal3 = (int num1, int num2) => { Console.WriteLine("通过Lambda表达计算:a+b={0}", num1 + num2); }; delCal3(100, 50); /* Lambda表达定义防方式:(参数列表)=>{方法体} =>读作goes to */ MathDelegate math1 = (int n) => { return(n * n); }; MathDelegate math2 = n => n * n;; //如果参数只有一个可以省略() 如果方法体只有一行代码可以省略{} CalculatorDelegate delCal4 = (p, q) => { var r1 = p + q; int r2 = p - q; Console.WriteLine("p+q={0}", r1); Console.WriteLine("p-q={0}", r2); }; Console.WriteLine(math1(10)); Console.WriteLine(math2(20)); delCal4(200, 100); #endregion #region 【5】自定义泛型委托和系统委托 Action/Func Console.WriteLine("\r\n--------------自定义泛型委托和系统委托------------------"); MyGenericDelegate <int, int> genericDelegate = GenericMethod; MyGenericDelegate <int, int> genericDelegate2 = delegate(int r1, int r2) { int result = r1 + r2; Console.WriteLine("泛型委托genericDelegate2调用的方法:" + result); }; MyGenericDelegate2 <int, int> genericDelegate3 = (r1, r2) => { Console.WriteLine("genericDelegate3是带有返回值的泛型委托变量"); return(r1 + r2); }; //系统也给我们提供了两个泛型委托,分别对应有返回值和无返回值 Action <int, int, int> myAction = (a1, a2, a3) => { int result = (a1 + a2) * a3; Console.WriteLine($"Action 调用结果 ${result}"); }; //Action泛型委托供给16个,也就是说参数最多可以是16个。 //Func泛型委托 Func <int, int, string> myFunc = (a1, a2) => { int result = a1 + a2; return("Func委托调用返回结果:" + result); }; genericDelegate(10, 20); genericDelegate2(10, 20); Console.WriteLine(genericDelegate3(10, 20)); myAction(1, 2, 3); Console.WriteLine(myFunc(1, 2)); #endregion #region 【6】逆变和协变 /* 在.Net 4之前,泛型接口是不能变化,.Net 4通过协变和逆变(抗变)为泛型接口、泛型委托添加一个重要的扩展。 * 协变和逆变是针对《参数》和《返回值》的类型进行自动转换。 * out(协变):放到方法的《返回值》前面,记忆:out 表示出 * in(逆变):放到方法《参数》前面 in 表示入 */ Person person1 = new Student(); //依据里氏替换原则 // Student stu =new Person();//不允许直接赋值的 List <Person> pList1 = new List <Person>(); // List<Person> pList2 = new List<Student>(); //如果某个返回值的类型可以由其派生类型替换,那么这个类型就是支持协变的。 //List实现了 IEnumerable接口,这个接口是支持协变的(可以通过F12查看元数据) IEnumerable <Person> pList3 = new List <Student>(); //逆变:如果某个参数的类型可以由其派生类型替换,那么这个类型就是支持逆变的 IPerson <Student> pList4 = new Teacher <Student>(); IPerson <Student> pList5 = new Teacher <Person>(); // 将子类 Student 用父类 Person 替换 #endregion #region 【7】扩展方法 /* * 扩展方法简单总结: * 不带参数的扩展方法定义: static 方法名 (this 目标类型 目标类型参数) * 带参数的扩展方法定义: static 方法名 (this 目标类型 目标类型参数,参数类型1,参数名2,… ) * this 关键字 : 表示可以向 this 关键字后面的类型添加扩展方法。 * 扩展方法使用中应该注意的问题: * 扩展方法必须定义在静态类中,扩展方法本身也是静态方法,扩展方法也可以重载。 * 如果扩展方法和对应的类位于不同的命名空间,使用时应引入扩展方法所在静态类的命名空间。 * 当类本身的方法与扩展方法重名时,类本身的方法被优先调用。(建议通过命名空间的方式来实现扩展方法的使用) * 扩展方法不要过多使用。尤其是系统定义的类,不要随意增加扩展方法。 */ Console.WriteLine("------------------扩展方法的更多应用---------------------"); List <Student> stuList = new List <Student> { new Student { StudentId = 1001, Age = 20, StudentName = "VIP学员001" }, new Student { StudentId = 1005, Age = 22, StudentName = "VIP学员002" }, new Student { StudentId = 1007, Age = 28, StudentName = "VIP学员003" }, new Student { StudentId = 1004, Age = 25, StudentName = "VIP学员004" }, new Student { StudentId = 1003, Age = 29, StudentName = "VIP学员005" } }; //使用扩展方法,轻松完成对象查找 var list = stuList.Where(s => s.Age > 25); Func <Student, bool> func = s => s.Age > 25; var list2 = stuList.Where(func); var list3 = stuList.Where(s => s.Age > 25).Select(s => s); var list4 = stuList.Where(s => s.Age > 25).Select(s => s.StudentName); foreach (var item in list) { Console.WriteLine($"{item.StudentId}\t{item.StudentName}\t{item.Age}"); } Console.WriteLine("---------------------------------------------------------------"); foreach (var item in list2) { Console.WriteLine($"{item.StudentId}\t{item.StudentName}\t{item.Age}"); } Console.WriteLine("---------------------------------------------------------------"); foreach (var item in list3) { Console.WriteLine($"{item.StudentId}\t{item.StudentName}\t{item.Age}"); } Console.WriteLine("---------------------------------------------------------------"); foreach (var item in list4) { Console.WriteLine(item); } Console.WriteLine("---------------------------------------------------------------"); var list5 = stuList.MyCustomWhere(s => s.Age < 25); foreach (var item in list5) { Console.WriteLine($"{item.StudentId}\t{item.StudentName}\t{item.Age}"); } #endregion Console.Read(); }
static void Main(string[] args) { #region 【1】使用var推断类型 //int stuAge = 20; var a = 20; var bookName = ".NET开发"; var student1 = new Student() { StudentName = "小张", Age = 22 }; Console.WriteLine(""); Console.WriteLine($"【1】var关键字的使用:共有{a} 个人在学习{bookName} 系列课程,其中{student1.StudentName} ,{student1.Age}岁,已经是高手了。"); //普通变量定义方法与var定义的比较 Student student2 = new Student() { StudentName = "小张", Age = 22 }; Console.WriteLine($"普通变量和Var变量是有一样的:{a}个人在学习{bookName} 其中{student1.StudentId} 已经是高手!"); //var和object有区别 var c = 2017; object b = 2020; b = ".Net高级进阶VIP课程"; //c = ""; //Var在匿名类中的使用(后面学习EF的时候,会大量使用) var person = new { Name = "王***", Age = 25, ClassName = ".Net全栈开发1班" }; Console.WriteLine("【4】var在匿名类中的使用-->姓名:{0} 年龄:{1} 班级:{2}", person.Name, person.Age, person.ClassName); #endregion #region 【2】委托基础 Console.WriteLine("\r\n------------------委托基础使用-------------------"); //2.3 创建委托对象(关联具体的方法) CalculatorDelegate delCal1 = new CalculatorDelegate(Add); // CalculatorDelegate delCal1 = Add //2.4 通过委托调用方法,而不是直接使用方法 delCal1(50, 20); //2.5 多路委托(多播委托) Console.WriteLine("------------------------------------------"); delCal1 += Sub; // delCal1(50, 20); Console.WriteLine("------------------------------------------"); delCal1 += Mul; delCal1(50, 20); //2.6 委托关联的移除 Console.WriteLine("------------------------------------------"); delCal1 -= Add; delCal1 -= Sub; delCal1(50, 20); //插曲:特性--> OOP的最高目标让我们程序高可扩展性,高性能,高效率! //特性的引入,在我们保证原有代码完整性不被破坏的前提下,会动态的植入我们需要的功能。 #endregion #region 【3】匿名方法 Console.WriteLine("\r\n-----------------匿名方法的使用------------------"); CalculatorDelegate delCal2 = delegate(int num1, int num2) { Console.WriteLine("通过匿名方法计算:a+b={0}", num1 + num2); }; delCal2(100, 50); //这个方法没有具体的名称,只有委托关键字,方法的参数,方法体,所以称为匿名方法 //匿名方法的使用:匿名方法允许委托变量作为参数传递,以代替单独方法的定义 #endregion #region 【4】Lambda表达式 //C#3.0时代,引入了Lambda表达式,利用他可以更加简练的编写代码块 Console.WriteLine("\r\n-----------------Lambda表达式的使用------------------"); CalculatorDelegate delCal3 = (int num1, int num2) => { Console.WriteLine("通过Lambda表达计算:a+b={0}", num1 + num2); }; delCal3(100, 50); //Lambda表达定义防方式:(参数列表)=>{方法体} =>读作goes to MathDelegate math1 = (int n) => { return(n * n); }; MathDelegate math2 = n => n * n;; //如果参数只有一个可以省略() 如果方法体只有一行代码可以省略{} CalculatorDelegate delCal4 = (p, q) => { var r1 = p + q; int r2 = p - q; Console.WriteLine("p+q={0}", r1); Console.WriteLine("p-q={0}", r2); }; Console.WriteLine(math1(10)); Console.WriteLine(math2(20)); delCal4(200, 100); //Lambda表达式中的参数类型可以是“明确类型”,也可以是“推断类型” // 如果是推断类型,则参数的数据类型是编译器根据上下文自动推断出来。 //Lambda表达式与匿名方法比较: //lambda表达式本身就是匿名方法。 //Lambda表达式参数允许不明确声明,而匿名方法参数类型必须明确指出。 //Lambda 表达式中方法体,允许单一表达式或者多条语句组成,而匿名方法不允许单一表达式。 #endregion #region 【5】自定义泛型委托和系统委托Action/Func MyGenericDelegate1 <int, int> genericDelegate1 = Test1; MyGenericDelegate1 <int, int> genericDelegate2 = delegate(int r1, int r2) { int result = r1 + r2; Console.WriteLine("泛型委托genericDelegate2调用的方法:" + result); }; MyGenericDelegate2 <int, int> genericDelegate3 = (r1, r2) => { Console.WriteLine("genericDelegate3是带有返回值的泛型委托变量"); return(r1 + r2); }; //系统也给我们提供了两个泛型委托,分别对应有返回值和无返回值 Action <int, int, int> myAction = (a1, a2, a3) => { int result = (a1 + a2) * a3; Console.WriteLine(result); }; //Action泛型委托供给16个,也就是说参数最多可以是16个。 //Func泛型委托 Func <int, int, string> myFunc = (a1, a2) => { int result = a1 + a2; return("Func委托调用返回结果:" + result); }; //后面扩展方法中Func有重要的意义... #endregion #region 【6】协变和逆变 //在.Net 4之前,泛型接口是不能变化,.Net 4通过协变和逆变(抗变)为泛型接口、泛型委托添加一个重要的扩展。 //协变和逆变是针对《参数》和《返回值》的类型进行自动转换。 //out(协变):放到方法的《返回值》前面,记忆:out 表示出 //in(逆变):放到方法《参数》前面 in 表示入 Person person1 = new Student();//依据里氏替换原则 // Student stu =new Person();//不允许直接赋值的 List <Person> pList1 = new List <Person>(); // List<Person> pList2 = new List<Student>(); //如果某个返回值的类型可以由其派生类型替换,那么这个类型就是支持协变的。 //List实现了 IEnumerable接口,这个接口是支持协变的(可以通过F12查看元数据) IEnumerable <Person> pList3 = new List <Student>(); //逆变:如果某个参数的类型可以由其派生类型替换,那么这个类型就是支持逆变的 IPerson <Student> pList4 = new Teacher <Student>(); IPerson <Student> pList5 = new Teacher <Person>();//将子类Student用父类Person替换 #endregion #region 【7】扩展方法 int scoreSum = 180; Console.WriteLine(scoreSum.ShowScore()); string[] nameList = { "小李", "小赵", "小刘" }; nameList.ShowList(); Student student = new Student { StudentName = "小李子" }; Console.WriteLine(student.GetAvg(90, 78)); List <int> ageList = new List <int> { 20, 34, 26 }; double avg = ageList.Average(); // 扩展方法简单总结: // 不带参数的扩展方法定义: static 方法名 (this 目标类型 目标类型参数) // 带参数的扩展方法定义: static 方法名 (this 目标类型 目标类型参数,参数类型1,参数名2,… ) // this关键字, 表示可以向this关键字后面的类型添加扩展方法。 // 扩展方法使用中应该注意的问题: // 扩展方法必须定义在静态类中,扩展方法本身也是静态方法,扩展方法也可以重载。 // 如果扩展方法和对应的类位于不同的命名空间,使用时应引入扩展方法所在静态类的命名空间。 // 当类本身的方法与扩展方法重名时,类本身的方法被优先调用。(建议通过命名空间的方式来现在扩展方法的使用) // 扩展方法不要过多使用。尤其是系统定义的类,不要随意增加扩展方法。 //特性、委托、扩展方法 Console.WriteLine("平均年龄:" + avg); //扩展方法的更多应用 Console.WriteLine("---------------------------------------------------------------"); List <Student> stuList = new List <Student> { new Student { StudentId = 1001, Age = 20, StudentName = "VIP学员001" }, new Student { StudentId = 1005, Age = 22, StudentName = "VIP学员002" }, new Student { StudentId = 1007, Age = 28, StudentName = "VIP学员003" }, new Student { StudentId = 1004, Age = 25, StudentName = "VIP学员004" }, new Student { StudentId = 1003, Age = 29, StudentName = "VIP学员005" } }; //使用扩展方法,轻松完成对象查找 var list1 = stuList.Where(s => s.Age > 25); Func <Student, bool> func = s => s.Age > 25; var list0 = stuList.Where(func); var list2 = stuList.Where(s => s.Age > 25).Select(s => s); var list3 = stuList.Where(s => s.Age > 25).Select(s => s.StudentName); foreach (var item in list1) { Console.WriteLine($"{item.StudentId}\t{item.StudentName}\t{item.Age}"); } Console.WriteLine("---------------------------------------------------------------"); foreach (var item in list2) { Console.WriteLine($"{item.StudentId}\t{item.StudentName}\t{item.Age}"); } Console.WriteLine("---------------------------------------------------------------"); foreach (var item in list3) { Console.WriteLine(item); } Console.WriteLine("---------------------------------------------------------------"); var list4 = stuList.MyCustomWhere(s => s.Age < 25); foreach (var item in list4) { Console.WriteLine($"{item.StudentId}\t{item.StudentName}\t{item.Age}"); } #endregion Console.Read(); }