1.委托的简介:
委托可以简单的理解为方法的列表,添加的方法的参数类型,个数,顺序必须和委托一致,
也就是说委托起到了托管方法的作用,并且约束了要调用的方法.
//1声明委托 public delegate void NoReturnNoPara(); public delegate void NoReturnWithPara(string name, int id); public delegate int WithReturnNoPara(); public delegate string WithReturnWithPara(string name);
基础代码:
private void ShowPerson(string name, int id) { Console.WriteLine("this is id={0} name={1}", id, name); }
ShowPerson
public class Student { public int Id { get; set; } public int ClassId { get; set; } public string Name { get; set; } public int Age { get; set; } public void Study() { Console.WriteLine("正在学习高级班"); } } /// <summary> /// 班级 /// </summary> public class Class { public int Id { get; set; } public string Name { get; set; } }
Student
{ Student student = new Student() { Id = , ClassId = , Name = "Courage-dhj" }; student.Study(); var people = new //匿名类 { Id = , ClassId = , Name = "Courage-dhj" }; Console.WriteLine("{0} {1} {2}", people.Id, people.Name, people.ClassId); }
匿名类
{ NoReturnWithPara method = new NoReturnWithPara(ShowPerson);//2 实例化委托 method.);//3 委托调用 ShowPerson();//方法的普通调用 }
2.匿名方法: 用delegate代替了方法名而已(修饰符和返回类型这里看作方法名)
{ NoReturnWithPara method = new NoReturnWithPara( delegate(string name, int id) { Console.WriteLine("this is id={0} name={1}", id, name); });//匿名方法 method.); }
3.Lambda表达式
{ NoReturnWithPara method = new NoReturnWithPara( (string name, int id) => { Console.WriteLine("this is id={0} name={1}", id, name); });//lambda表达式 把delegate换成箭头 method.Invoke(); //lambda表达式的本质就是一个匿名方法,,也就是一个方法 }
因为委托对方法有约束作用,所以,方法的参数类型可以省略
{ NoReturnWithPara method = new NoReturnWithPara( (name, id) =>//lambda表达式方法主体只有一行,可以去掉大括号和分号 Console.WriteLine("this is id={0} name={1}", id, name) ); method.Invoke(); }
其他的形式:
{ NoReturnWithPara method = new NoReturnWithPara( (name, id) =>//lambda表达式方法主体只有一行,可以去掉大括号和分号 Console.WriteLine("this is id={0} name={1}", id, name) ); method.Invoke(); }
{ //new一个委托的时候,可以简写 NoReturnWithPara method = (name, id) => Console.WriteLine("this is id={0} name={1}", id, name);//常用的形式 method.Invoke(); }
4. Action 和 Func----这是系统自带的委托,方便我们使用.
4.1-Action-无返回值的委托---看下面的in也看的出来啦!
先查看系统代码的说明:
namespace System { // 摘要: // 封装一个方法,该方法不具有参数并且不返回值。 [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] public delegate void Action(); }
Action(一个参数)
namespace System { // 摘要: // 封装一个方法,该方法只有一个参数并且不返回值。 // // 参数: // obj: // 此委托封装的方法的参数。 // // 类型参数: // T: // 此委托封装的方法的参数类型。 public delegate void Action<in T>(T obj); }
Action(in T)
namespace System { // 摘要: // 封装一个方法,该方法具有 16 个参数并且不返回值。 // // 参数: // arg1: // 此委托封装的方法的第一个参数。 // // arg2: // 此委托封装的方法的第二个参数。 // // arg3: // 此委托封装的方法的第三个参数。 // // arg4: // 此委托封装的方法的第四个参数。 // // arg5: // 此委托封装的方法的第五个参数。 // // arg6: // 此委托封装的方法的第六个参数。 // // arg7: // 此委托封装的方法的第七个参数。 // // arg8: // 此委托封装的方法的第八个参数。 // // arg9: // 此委托封装的方法的第九个参数。 // // arg10: // 此委托封装的方法的第十个参数。 // // arg11: // 此委托封装的方法的第十一个参数。 // // arg12: // 此委托封装的方法的第十二个参数。 // // arg13: // 此委托封装的方法的第十三个参数。 // // arg14: // 此委托封装的方法的第十四个参数。 // // arg15: // 此委托封装的方法的第十五个参数。 // // arg16: // 此委托封装的方法的第十六个参数。 // // 类型参数: // T1: // 此委托封装的方法的第一个参数类型。 // // T2: // 此委托封装的方法的第二个参数类型。 // // T3: // 此委托封装的方法的第三个参数类型。 // // T4: // 此委托封装的方法的第四个参数类型。 // // T5: // 此委托封装的方法的第五个参数的类型。 // // T6: // 此委托封装的方法的第六个参数的类型。 // // T7: // 此委托封装的方法的第七个参数的类型。 // // T8: // 此委托封装的方法的第八个参数的类型。 // // T9: // 此委托封装的方法的第九个参数的类型。 // // T10: // 此委托封装的方法的第十个参数的类型。 // // T11: // 此委托封装的方法的第十一个参数的类型。 // // T12: // 此委托封装的方法的第十二个参数的类型。 // // T13: // 此委托封装的方法的第十三个参数的类型。 // // T14: // 此委托封装的方法的第十四个参数的类型。 // // T15: // 此委托封装的方法的第十五个参数的类型。 // // T16: // 此委托封装的方法的第十六个参数的类型。 public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); }
系统封装-最多16个参数
实例化:
//接受0到16个参数的 无返回值 泛型委托 Action act1 = () => Console.WriteLine( Action< Action<Student, Class,
4.2. Func---有返回值---看out就看得出来啦!
namespace System { // 摘要: // 封装一个不具有参数但却返回 TResult 参数指定的类型值的方法。 // // 类型参数: // TResult: // 此委托封装的方法的返回值类型。 // // 返回结果: // 此委托封装的方法的返回值。 [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] public delegate TResult Func<out TResult>(); }
无参数,有一个返回值
namespace System { // 摘要: // 封装一个具有一个参数并返回 TResult 参数指定的类型值的方法。 // // 参数: // arg: // 此委托封装的方法的参数。 // // 类型参数: // T: // 此委托封装的方法的参数类型。 // // TResult: // 此委托封装的方法的返回值类型。 // // 返回结果: // 此委托封装的方法的返回值。 [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")] public delegate TResult Func<in T, out TResult>(T arg); }
一个in,一个out
namespace System { // 摘要: // 封装一个方法,该方法具有 16 个参数,并返回 TResult 参数所指定的类型的值。 // // 参数: // arg1: // 此委托封装的方法的第一个参数。 // // arg2: // 此委托封装的方法的第二个参数。 // // arg3: // 此委托封装的方法的第三个参数。 // // arg4: // 此委托封装的方法的第四个参数。 // // arg5: // 此委托封装的方法的第五个参数。 // // arg6: // 此委托封装的方法的第六个参数。 // // arg7: // 此委托封装的方法的第七个参数。 // // arg8: // 此委托封装的方法的第八个参数。 // // arg9: // 此委托封装的方法的第九个参数。 // // arg10: // 此委托封装的方法的第十个参数。 // // arg11: // 此委托封装的方法的第十一个参数。 // // arg12: // 此委托封装的方法的第十二个参数。 // // arg13: // 此委托封装的方法的第十三个参数。 // // arg14: // 此委托封装的方法的第十四个参数。 // // arg15: // 此委托封装的方法的第十五个参数。 // // arg16: // 此委托封装的方法的第十六个参数。 // // 类型参数: // T1: // 此委托封装的方法的第一个参数类型。 // // T2: // 此委托封装的方法的第二个参数类型。 // // T3: // 此委托封装的方法的第三个参数类型。 // // T4: // 此委托封装的方法的第四个参数类型。 // // T5: // 此委托封装的方法的第五个参数的类型。 // // T6: // 此委托封装的方法的第六个参数的类型。 // // T7: // 此委托封装的方法的第七个参数的类型。 // // T8: // 此委托封装的方法的第八个参数的类型。 // // T9: // 此委托封装的方法的第九个参数的类型。 // // T10: // 此委托封装的方法的第十个参数的类型。 // // T11: // 此委托封装的方法的第十一个参数的类型。 // // T12: // 此委托封装的方法的第十二个参数的类型。 // // T13: // 此委托封装的方法的第十三个参数的类型。 // // T14: // 此委托封装的方法的第十四个参数的类型。 // // T15: // 此委托封装的方法的第十五个参数的类型。 // // T16: // 此委托封装的方法的第十六个参数的类型。 // // TResult: // 此委托封装的方法的返回值类型。 // // 返回结果: // 此委托封装的方法的返回值。 public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); }
系统最多16个in参数
不过,不管怎么变,Func的最后一个始终都时out,因为它时有返回值的呗!
//注意:这是一个新的类型,类型的不同包括了参数的个数的哦. public delegate TResult ; Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, in T17, out TResult> (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17);
如果16个参数不够的话
//接受0到16个参数的 带返回值 泛型委托 Func<int> func1 = () => DateTime.Now.Millisecond;//4--返回int类型 //下面都返回string类型 Func< Func<Student, Class, //调用自己写的,17个参数 Func<Student, Student, Class,
5 扩展方法: 静态类的静态方法第一个参数加上 this.(静态类不一定要加上static,只要有静态方法的类就是静态类)
/// <summary> /// 静态类的静态方法,第一个参数前面加上this /// </summary> public static class ExtendTest { /// <summary> /// 转成int 失败给0写日志 /// </summary> /// <param name="sNumber"></param> /// <returns></returns> public static int ToInt(this string sNumber) { ; if (int.TryParse(sNumber, out iNumber)) { return iNumber; } else { Console.WriteLine("{0} 转换失败,给出默认值", sNumber); ; } } public static void Study(this Student student) { Console.WriteLine("); } public static void StudyVip(this Student student) { Console.WriteLine("); } public static void ConsoleShow(this object oValue) { Console.WriteLine(oValue); } }
调用: 就像给某个类添加了一个方法一样,所以才叫扩展方法啊!
"; ExtendTest.ToInt(sNumber);//普通调用--返回一个int sNumber.ToInt();//扩展方法调用--返回一个int Student student = new Student() { Name = "天道无情(387-天道无情-男)" }; student.StudyVip(); student.Study(); student.ConsoleShow();
不过,扩展方法并非给this 修饰的类添加了一个方法,而是通过this添加了一个纽带.
当我们调用扩展方法时,还是进入了我们自己写的方法里.
只不过它看起来像时我们给一个类注入了一个方法而已.(这里用注入很形象的形容)
记住:扩展方法时写在一个外部的静态类里,并且是一个静态方法,参数类型前加this.
6. Linq 查询
private static List<Student> GetStudentList() { #region 初始化数据 List<Student> studentList = new List<Student>() { new Student() { Id=, Name="Answer(学委-answer-男)", Age=, ClassId= }, new Student() { Id=, Name=" LTS_信仰I(196-LTS_信仰I-男-深圳)", Age=, ClassId= }, new Student() { Id=, Name="ObjectIsNotFound", Age=, ClassId= }, new Student() { Id=, Name="落单的候鸟", Age=, ClassId= }, new Student() { Id=, Name="夜的乐章", Age=, ClassId= }, new Student() { Id=, Name="知心dě朋友=(357-杰仔-男-广州)", Age=, ClassId= }, new Student() { Id=, Name="我", Age=, ClassId= }, new Student() { Id=, Name="小逸", Age=, ClassId= }, new Student() { Id=, Name="季雨林", Age=, ClassId= }, new Student() { Id=, Name="dean", Age=, ClassId= }, new Student() { Id=, Name="yup_h", Age=, ClassId= } }; #endregion 初始化数据 return studentList; }
Linq用到的数据
普通程序员一般会想的方法:
List<Student> studentList = GetStudentList(); { List<Student> targetList = new List<Student>(); foreach (var item in studentList) { ) { targetList.Add(item); } } }
Linq查询和Lambda表达式查询:
// // 摘要: // 基于谓词筛选值序列。 // // 参数: // source: // 要筛选的 System.Collections.Generic.IEnumerable<T>。 // // predicate: // 用于测试每个元素是否满足条件的函数。 // // 类型参数: // TSource: // source 中的元素的类型。 // // 返回结果: // 一个 System.Collections.Generic.IEnumerable<T>,包含输入序列中满足条件的元素。 // // 异常: // System.ArgumentNullException: // source 或 predicate 为 null。 public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
Where
注:Where本身是一个扩展方法.
Lambda
{ Console.WriteLine("**************************"); );//陈述式 foreach (var item in targetList) { Console.WriteLine(" {0} {1}", item.Age, item.Name); } Console.WriteLine("**************************");
Linq
Console.WriteLine("**************************"); var list = from s in studentList select s; foreach (var item in list) { Console.WriteLine(" {0} {1}", item.Age, item.Name); }
为了弄懂原理,请看下面:
7. Lambda查询模拟器:
this IEnumerable<TSource> source 是数据源
Func<TSource, bool> predicate 是查找的方法,第一个参数是传入参数in,后一个是返回类型-用于判断.
public static class ElevenExtend { public static IEnumerable<TSource> ElevenWhere<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) { if (source == null) throw new Exception("null"); List<TSource> tList = new List<TSource>(); foreach (var item in source) { if (predicate.Invoke(item)) //调用时会返回一个bool tList.Add(item); } return tList; } }
private static bool CheckStudentAge(Student student) { ; }
调用:
Func<Student, bool> func = new Func<Student, bool>(CheckStudentAge); //t => t.Age > 25; var targetListEleven = studentList.ElevenWhere<Student>(func);//陈述式
foreach (var item in targetListEleven) { Console.WriteLine(" {0} {1}", item.Age, item.Name); }
8. 其他的查询:
{ Console.WriteLine("**************************"); || t.Name.Contains(, }.Contains(t.ClassId));//陈述式 foreach (var item in targetList) { Console.WriteLine(" {0} {1}", item.Age, item.Name); } }
// // 摘要: // 将序列中的每个元素投影到新表中。 // // 参数: // source: // 一个值序列,要对该序列调用转换函数。 // // selector: // 应用于每个元素的转换函数。 // // 类型参数: // TSource: // source 中的元素的类型。 // // TResult: // selector 返回的值的类型。 // // 返回结果: // 一个 System.Collections.Generic.IEnumerable<T>,其元素为对 source 的每个元素调用转换函数的结果。 // // 异常: // System.ArgumentNullException: // source 或 selector 为 null。 public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector);
Select投影查询
{ var list = studentList.Select(s => new { IdAge = string.Format("{0}_{1}", s.Id, s.Age), Name = s.Name }); Console.WriteLine("**************************"); foreach (var student in list) { Console.WriteLine("Name={0} Age={1}", student.Name, student.IdAge); } }
对应的linq
{ var list = from student in studentList // select new { IdAge = string.Format("{0}_{1}", student.Id, student.Age), Name = student.Name };//语法糖 Console.WriteLine("**************************"); foreach (var student in list) { Console.WriteLine("Name={0} Age={1}", student.Name, student.IdAge); } }
{ Console.WriteLine("**************************"); && s.Id < ) .Select<Student, Student>(s => //Skip是跳过 Take是获取 new Student { Age = s.Age, Name = string.Format("{0}_{1}", s.Name, s.Id) }) .OrderBy<Student, int>(s => s.Id) .OrderByDescending<Student, int>(s => s.Age) .Skip<Student>()//跳过1个 .Take<Student>())//获取5个 { Console.WriteLine("Name={0} Age={1}", student.Name, student.Age); } }
注:linq查询编译后还是调用的Lambda表达式.