


?委托:
l 什么委托:
本质是方法指针
l 委托的作用:
作用:进行方法传递,方法可以当作一个参数进行传递,C#里边要传递方法需要借助委托
l 使用委托一般的步骤:
1:定义委托
public delegate 返回值 方法名称(参数);
2:委托可以关联方法
3:执行委托,就相当于执行方法
- public static void Way()
- {
- Console.WriteLine("hello delegate");
- }
- //1:定义一个无参数无返回值的委托
- public delegate void DEL_Way();
- static void Main(string[] args)
- {
- //2:给委托关联一个方法
- DEL_Way delway = Way;
- //3:执行委托
- delway.Invoke();
- Console.ReadLine();
- }
l 委托实现一个简单的定时器:
- public class MyTimer
- {
- public void Start(Action way, int timespan)
- {
- while (true)
- {
- way();
- System.Threading.Thread.Sleep(timespan);
- }
- }
- }
执行:
- MyTimer mytimer = new MyTimer();
- mytimer.Start(Way, 1000);
?系统委托
作用:简化委托的定义,系统已经定义好,使用的时候直接使用,不需要重复定义
l 系统委托的主要分类
Action:无返回值,有0-16个参数
Func:有返回值,有0-16个参数
Predicate:固定返回值为bool
Comparison:固定返回值为int
其实后面两个完全可以使用func替换,但是为了一目了然一看就知道返回值是什么
l 实例
- Action action = Way;
- action();
- Action<int> action2 = Square;
- action2(6);
- Func<int, int, int> func = Add;
- int result = func(8, 8);
- Console.WriteLine(result);
?Lamdba表达式
l 作用:
lamdba表达式可以简化方法的定义
l 语法:
(方法参数)=>{方法体};
例如:无参无返回值的lamdba表达式
()=>{};
又如:一个参数无返回值
(a)=>{};
在如:一个参数一个返回值
(a)=>{return a*a};
还如:2个参数1个返回值
(a,b)=>{return a+b};
l 实例:
- //无参无返回值的lamdba表达式
- Action action = () => { Console.WriteLine("hello lamdba"); };
- action();
-
- //一个参数无返回值
- Action<int> action2 = (a) => { Console.WriteLine(a * a); };
- action2(6);
-
- //一个参数一个返回值
- Func<int, int> func = (a) => { return a * a; };
- int square = func(8);
- Console.WriteLine(square);
-
- //2个参数1个返回值
- Func<int, int, int> funcsum = (a, b) => { return a + b; };
- int result = funcsum(3, 6);
- Console.WriteLine(result);
执行定时器的就可以用lamdba来简化方法:
- MyTimer mytime = new MyTimer();
- mytime.Start(() =>
- {
- Console.WriteLine("国庆快乐");
- }, 1000);
做一点简单的集合查询:
- static void Main(string[] args)
- {
- List<string> fruitList = new List<string>() { "葡萄", "香蕉", "西瓜", "木瓜", "哈密瓜" };
- Console.WriteLine("请输入查询名字");
- string fruitName = Console.ReadLine();
- var result = fruitList.Where(a => a.Contains(fruitName));
- Console.ReadLine();
- }
对象集合lamdba查询:
- static void Main(string[] args)
- {
- List<Users> ulist = new List<Users>() {
- new Users() {username="李清照", age=23, address="宋" },
- new Users() {username="黄月英", age=18, address="三国" },
- new Users() {username="黄忠", age=109, address="三国" },
- new Users() {username="黄蓉", age=27, address="射雕" }
- };
- Console.WriteLine("请输入查询姓名");
- string name = Console.ReadLine();
- var result = ulist.Where(a => a.username.Contains(name)).OrderByDescending(a => a.age).ToList();
- Console.ReadLine();
- }
?Lamdba表达式自己实现foreach,Where,FirstOrDefault,SelectMany
自己实现一下微软提供的集合查询也算是抛砖引玉了
- public static class IEnumerableExtands
- {
- public static void MyForEach<T>(this IEnumerable<T> source, Action<T> action)
- {
- foreach (T item in source)
- {
- action(item);
- }
- }
- //根据条件查询
- public static IEnumerable<T> MyWhere<T>(this IEnumerable<T> source, Predicate<T> action)
- {
- List<T> list = new List<T>();
- foreach (T item in source)
- {
- if (action(item))
- {
- list.Add(item);
- }
- }
- return list;
- }
- //根据条件查询返回第一条或者默认值
- public static T MyFirstOrDefault<T>(this IEnumerable<T> source, Predicate<T> action)
- {
- T val = default(T);
- foreach (T item in source)
- {
- if (action(item))
- {
- return item;
- }
- }
- return val;
- }
- }
效果:
实现集合查询SelectMany
自己写一下里边的原理对了解它的用法有很大的帮助,select都作用类似就是把1对多的格式处理成1对1的格式,
比如这里的把UserScoreViewModel格式处理成UserScoreViewModel2
我们要想写通用的扩展方法出来可以先写一个专门的处理UserScoreViewModel格式成UserScoreViewModel2的方法,这样做也便于我们分析和理解问题,特别是如果我们要进行授课,这种方式更能够让学生理解,一步一步的深入。
其实很简单就是两个遍历就好
- /// <summary>
- /// 把List<UserScoreViewModel>转换成List<UserScoreViewModel2>格式
- /// </summary>
- public List<UserScoreViewModel2> Parse(List<UserScoreViewModel> source)
- {
- List<UserScoreViewModel2> result = new List<UserScoreViewModel2>();
- foreach (UserScoreViewModel item in source)
- {
- foreach (Score scoreItem in item.scoreList)
- {
- UserScoreViewModel2 uscore = new UserScoreViewModel2();
- uscore.UserName = item.UserName;
- uscore.score = scoreItem;
- result.Add(uscore);
- }
- }
- return result;
- }
然后我们在去写通用的:
- public static class IEnumberExtands
- {
- /// <summary>
- /// 自己实现MySelectMany
- /// </summary>
- /// <typeparam name="TSource">对应外面的集合源类型</typeparam>
- /// <typeparam name="TCollection">集合里边子集合类型</typeparam>
- /// <typeparam name="TResult">返回值类型</typeparam>
- /// <returns></returns>
- public static IEnumerable<TResult> MySelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
- {
- List<TResult> resultList = new List<TResult>();
- foreach (TSource tsource in source)
- {
- //通过外面传递的lamdba拿到集合
- IEnumerable<TCollection> sublist = collectionSelector(tsource);
- foreach (TCollection item in sublist)
- {
- //通过外面传递的lamdba拿到返回对象
- TResult result = resultSelector(tsource, item);
- resultList.Add(result);
- }
- }
- return resultList;
- }
- }
上面的方法没有处理为空的情况,如果外面写了DefaultIfEmpty()就容易报错,所以我们可以使用反射创建一个默认对象处理一下这种情况,不然我们就只有在外面去处理了
- public static IEnumerable<TResult> MySelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
- {
- List<TResult> userScoreViewModel2List = new List<TResult>();
- foreach (TSource item in source)
- {
- foreach (TCollection score in collectionSelector(item))
- {
- if (score == null)
- {
- //使用反射创建对象,避免为空报错,为空的时候我们就给一个默认值
- TCollection collobj = Activator.CreateInstance<TCollection>();
- TResult tresult = resultSelector(item, collobj);
- userScoreViewModel2List.Add(tresult);
- }
- else
- {
- TResult tresult = resultSelector(item, score);
- userScoreViewModel2List.Add(tresult);
- }
- }
- }
- return userScoreViewModel2List;
- }
最后这个还想说一点,我们使用通用的selectMany方法,并没有使用反射,而是通过外面传递的lamdba表达式,也就是外面传递的方法来实现这个通用的功能,从这里也可以看出来通过方法传递来实现一个功能是非常灵活的,可以写出很通用的代码。
当然我们这里是解析的集合,而不是解析的sql语句,如果是解析sql语句我们这里应该就是传递的表达式树了,ef中解析sql语句的selectMany原理后面有机会在说
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739。有需要软件开发,或者学习软件技术的朋友可以和我联系~(Q:815170684)