应无所住,而生其心
排名
1
文章
860
粉丝
112
评论
163
net core webapi post传递参数
庸人 : 确实坑哈,我也是下班好了好几次,发现后台传递对象是可以的,但...
百度编辑器自定义模板
庸人 : 我建议换个编辑器,因为现在百度富文本已经停止维护了,用tinymec...
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

C#委托与lamdba表达式入门,以及Lamdba自己实现SelectMany等

6045人阅读 2019/9/29 11:17 总访问:5182399 评论:0 收藏:0 手机
分类: .NET


 ?委托:

l  什么委托:

            本质是方法指针

l  委托的作用:

   作用:进行方法传递,方法可以当作一个参数进行传递,C#里边要传递方法需要借助委托

l  使用委托一般的步骤:

         1:定义委托

              public delegate 返回值 方法名称(参数);

         2:委托可以关联方法

         3:执行委托,就相当于执行方法

    1. public static void Way()
    2. {
    3.     Console.WriteLine("hello delegate");
    4. }
    5. //1:定义一个无参数无返回值的委托
    6. public delegate void DEL_Way();
    7. static void Main(string[] args)
    8. {
    9.     //2:给委托关联一个方法
    10.     DEL_Way delway = Way;
    11.     //3:执行委托
    12.     delway.Invoke();
    13.     Console.ReadLine();
    14. }

     

  l  委托实现一个简单的定时器:

  1. public class MyTimer
  2. {
  3.     public void Start(Action way, int timespan)
  4.     {
  5.         while (true)
  6.         {
  7.             way();
  8.             System.Threading.Thread.Sleep(timespan);
  9.         }
  10.     }
  11. }

        执行:

  1. MyTimer mytimer = new MyTimer();
  2. mytimer.Start(Way, 1000);

 

 ?系统委托

  作用:简化委托的定义,系统已经定义好,使用的时候直接使用,不需要重复定义

 

l  系统委托的主要分类

   Action:无返回值,有0-16个参数

  Func:有返回值,有0-16个参数

          Predicate:固定返回值为bool

          Comparison:固定返回值为int

          其实后面两个完全可以使用func替换,但是为了一目了然一看就知道返回值是什么

      l  实例

  1. Action action = Way;
  2. action();
  3. Action<int> action2 = Square;
  4. action2(6);
  5. Func<intintint> func = Add;
  6. int result = func(88);
  7. Console.WriteLine(result);


?Lamdba表达式

 l  作用:

lamdba表达式可以简化方法的定义

 l  语法: 

   (方法参数)=>{方法体};

   例如:无参无返回值的lamdba表达式

    ()=>{};

       又如:一个参数无返回值

                 (a)=>{};

       在如:一个参数一个返回值

                 (a)=>{return a*a};

       还如:2个参数1个返回值             

                 (a,b)=>{return a+b};

    l  实例:

  1. //无参无返回值的lamdba表达式
  2. Action action = () => { Console.WriteLine("hello lamdba"); };
  3. action();
  4. //一个参数无返回值
  5. Action<int> action2 = (a) => { Console.WriteLine(a * a); };
  6. action2(6);
  7. //一个参数一个返回值
  8. Func<intint> func = (a) => { return a * a; };
  9. int square = func(8);
  10. Console.WriteLine(square);
  11. //2个参数1个返回值
  12. Func<intintint> funcsum = (a, b) => { return a + b; };
  13. int result = funcsum(36);
  14. Console.WriteLine(result);

    执行定时器的就可以用lamdba来简化方法:

  1. MyTimer mytime = new MyTimer();
  2. mytime.Start(() =>
  3. {
  4.     Console.WriteLine("国庆快乐");
  5. }, 1000);

    做一点简单的集合查询:

  1. static void Main(string[] args)
  2. {
  3.     List<string> fruitList = new List<string>() { "葡萄""香蕉""西瓜""木瓜""哈密瓜" };
  4.     Console.WriteLine("请输入查询名字");
  5.     string fruitName = Console.ReadLine();
  6.     var result = fruitList.Where(a => a.Contains(fruitName));
  7.     Console.ReadLine();
  8. }

     对象集合lamdba查询:

  1. static void Main(string[] args)
  2. {
  3.     List<Users> ulist = new List<Users>() {
  4.         new Users() {username="李清照", age=23, address="宋" },
  5.         new Users() {username="黄月英", age=18, address="三国" },
  6.         new Users() {username="黄忠", age=109, address="三国" },
  7.         new Users() {username="黄蓉", age=27, address="射雕" }
  8.     };
  9.     Console.WriteLine("请输入查询姓名");
  10.     string name = Console.ReadLine();
  11.     var result = ulist.Where(a => a.username.Contains(name)).OrderByDescending(a => a.age).ToList();
  12.     Console.ReadLine();
  13. }


?Lamdba表达式自己实现foreach,Where,FirstOrDefault,SelectMany

自己实现一下微软提供的集合查询也算是抛砖引玉了

  1. public static class IEnumerableExtands
  2. {
  3.     public static void MyForEach<T>(this IEnumerable<T> source, Action<T> action)
  4.     {
  5.         foreach (T item in source)
  6.         {
  7.             action(item);
  8.         }
  9.     }
  10.     //根据条件查询
  11.     public static IEnumerable<T> MyWhere<T>(this IEnumerable<T> source, Predicate<T> action)
  12.     {
  13.         List<T> list = new List<T>();
  14.         foreach (T item in source)
  15.         {
  16.             if (action(item))
  17.             {
  18.                 list.Add(item);
  19.             }
  20.         }
  21.         return list;
  22.     }
  23.     //根据条件查询返回第一条或者默认值
  24.     public static T MyFirstOrDefault<T>(this IEnumerable<T> source, Predicate<T> action)
  25.     {
  26.         T val = default(T);
  27.         foreach (T item in source)
  28.         {
  29.             if (action(item))
  30.             {
  31.                 return item;
  32.             }
  33.         }
  34.         return val;
  35.     }
  36. }

效果:

实现集合查询SelectMany

自己写一下里边的原理对了解它的用法有很大的帮助,select都作用类似就是把1对多的格式处理成1对1的格式,

比如这里的把UserScoreViewModel格式处理成UserScoreViewModel2

我们要想写通用的扩展方法出来可以先写一个专门的处理UserScoreViewModel格式成UserScoreViewModel2的方法,这样做也便于我们分析和理解问题,特别是如果我们要进行授课,这种方式更能够让学生理解,一步一步的深入。

其实很简单就是两个遍历就好

  1. /// <summary>
  2. /// 把List<UserScoreViewModel>转换成List<UserScoreViewModel2>格式
  3. /// </summary>
  4. public List<UserScoreViewModel2> Parse(List<UserScoreViewModel> source)
  5. {
  6.     List<UserScoreViewModel2> result = new List<UserScoreViewModel2>();
  7.     foreach (UserScoreViewModel item in source)
  8.     {
  9.         foreach (Score scoreItem in item.scoreList)
  10.         {
  11.             UserScoreViewModel2 uscore = new UserScoreViewModel2();
  12.             uscore.UserName = item.UserName;
  13.             uscore.score = scoreItem;
  14.             result.Add(uscore);
  15.         }
  16.     }
  17.     return result;
  18. }

然后我们在去写通用的:

  1. public static class IEnumberExtands
  2. {
  3.     /// <summary>
  4.     /// 自己实现MySelectMany
  5.     /// </summary>
  6.     /// <typeparam name="TSource">对应外面的集合源类型</typeparam>
  7.     /// <typeparam name="TCollection">集合里边子集合类型</typeparam>
  8.     /// <typeparam name="TResult">返回值类型</typeparam>
  9.     /// <returns></returns>
  10.     public static IEnumerable<TResult> MySelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
  11.     {
  12.         List<TResult> resultList = new List<TResult>();
  13.         foreach (TSource tsource in source)
  14.         {
  15.             //通过外面传递的lamdba拿到集合
  16.             IEnumerable<TCollection> sublist = collectionSelector(tsource);
  17.             foreach (TCollection item in sublist)
  18.             {
  19.                 //通过外面传递的lamdba拿到返回对象
  20.                 TResult result = resultSelector(tsource, item);
  21.                 resultList.Add(result);
  22.             }
  23.         }
  24.         return resultList;
  25.     }
  26. }

上面的方法没有处理为空的情况,如果外面写了DefaultIfEmpty()就容易报错,所以我们可以使用反射创建一个默认对象处理一下这种情况,不然我们就只有在外面去处理了

  1. public static IEnumerable<TResult> MySelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
  2. {
  3.     List<TResult> userScoreViewModel2List = new List<TResult>();
  4.     foreach (TSource item in source)
  5.     {
  6.         foreach (TCollection score in collectionSelector(item))
  7.         {
  8.             if (score == null)
  9.             {
  10.                 //使用反射创建对象,避免为空报错,为空的时候我们就给一个默认值
  11.                 TCollection collobj = Activator.CreateInstance<TCollection>();
  12.                 TResult tresult = resultSelector(item, collobj);
  13.                 userScoreViewModel2List.Add(tresult);
  14.             }
  15.             else
  16.             {
  17.                 TResult tresult = resultSelector(item, score);
  18.                 userScoreViewModel2List.Add(tresult);
  19.             }
  20.         }
  21.     }
  22.     return userScoreViewModel2List;
  23. }

最后这个还想说一点,我们使用通用的selectMany方法,并没有使用反射,而是通过外面传递的lamdba表达式,也就是外面传递的方法来实现这个通用的功能,从这里也可以看出来通过方法传递来实现一个功能是非常灵活的,可以写出很通用的代码。

当然我们这里是解析的集合,而不是解析的sql语句,如果是解析sql语句我们这里应该就是传递的表达式树了,ef中解析sql语句的selectMany原理后面有机会在说



欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739。有需要软件开发,或者学习软件技术的朋友可以和我联系~(Q:815170684)

评价

Css弹性盒子,flex布局

css弹性盒子由于版本不同浏览器问题造成了一些不同的写法display:flexbox;在google浏览器中如果使用下面的写法就不行displa...

Css图片和文字对齐问题

文字和图片写到一排经常会出现对不齐的问题 这样感觉图片会上来一点没有和文字对齐,如下图 但是如果修改下html结...

GitHub 上传项目

补充简化方法:登录git创建项目--&gt;拉取刚刚创建的项目--&gt;复制需要的代码进去--&gt;上传提交即可先拉取项目在上传代码...

NET Core 使用 EF Code First

下面这些内容很老了看这篇:https://www.tnblog.net/aojiancc2/article/details/5365 项目使用多层,把数据库访问...

Windows平台分布式架构实践 - 负载均衡

原文地址: https://www.cnblogs.com/atree/p/windows_loadbalancer.html 概述  最近.NET的世界开始闹腾了,微软官方终...

Css实现简单矩形对话框

在前端做项目时,我们可能会遇到写对话框的需求,这次做视频会议页面就遇到了,记录下日后有个参照。//网页部分 &lt;divcla...

CAPS.NET 保存base64位格式的图片

publicvoidUpload() { //取出图片对应的base64位字符 stringimgBase=Request[&quot;imgBase&quot;]; //c#里边的base6...

使用OLEDB读取不同版本ExCel的连接字符串设置

使用OleBD读取excel的时候,excel不同的版本,连接字符串的写法也会不一样。///&lt;summary&gt; ///读取excel ///&lt;/su...

vs2017 对 COM 组件的调用返回了错误 HRESULT E_FAIL

vs2017添加引用报错 对 COM 组件的调用返回了错误 HRESULT E_FAIL 1.以管理员身份打开vs2017开发人员命令指示符 2...

分布式服务架构与微服务架构概念的区别与联系

分布式:分散压力。微服务:分散能力。当下理解分布式:不同模块部署在不同服务器上作用:分布式解决网站高并发带来问题集...

分布式-微服务-集群的区别

1.分布式将一个大的系统划分为多个业务模块,业务模块分别部署到不同的机器上,各个业务模块之间通过接口进行数据交互。区...

NPOI操作exCel 2007/2010版本

HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xlsXSSFWorkbook:是操作Excel2007的版本,扩展名是.xlsx先...

这样学英语三个月超过你过去学三年

本文作者三年间从四级勉强及格到高级口译笔试210,口试232。找工作面试时给其口试的老外考官听了一分钟就说你的英语不用考...

EasyUI弹窗批量修改Combogrid下拉框的值

JS方法//点击弹出批量修改框 UpdateLot:function(){ varrow=$(&quot;#dg&quot;).datagrid(&quot;getChecked&quot;); if(...

js与Controller中分割字符串的方法

js: varstr=OpenRule; varstrs=newArray(); strs=str.split(&quot;,&quot;); for(vari=0;i&lt;strs.length;i++){ $(&q...

如何修改CSS中存在的element.style内联样式

改腾讯地图的时候调整了下样式,发现样式一直存在问题,修改style里面的值,一点用都没有,html中这个值还找不到是在哪里出...