前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >在VS中调试LINQ(Lambda)

在VS中调试LINQ(Lambda)

原创
作者头像
过千帆
修改于 2021-04-08 07:03:34
修改于 2021-04-08 07:03:34
4.7K0
举报
文章被收录于专栏:过千帆博客过千帆博客

来源:https://note.guoqianfan.com/2021/03/21/debug-linq-with-vs/

前言

Linq调试有3种方法,准确来说是2种,因为LinqPad算是复制代码段到外部了。。

  1. VS自带调试:lambda表达式打断点
  2. VS插件OzCode
  3. LinqPad

VS自带调试

在VS里,是可以对Linq调试的,不过一般打断点都会打在整个语句上,这时候我们要换个打法,把断点打在lambda表达式上。

注意和前提

  1. Linq是Linq to object
  2. 对于Linq to object,只有集合对象是 IEnumerable 时,才能命中到Linq里的lambda表达式,IQueryable是不行的。如果是IQueryable,此时就算在lambda表达式里打上断点,在代码执行时,断点会向上转移到整个语句上。 如果是IQueryable,在lambda表达式里打上断点和设置操作,操作会输出错误:order name: id=error CS0103: 当前上下文中不存在名称“p”, name=error CS0103: 当前上下文中不存在名称“p”
  3. 对于Linq to object,当集合对象是 IEnumerable 时,是延迟执行的。只有结果被用到时,才会进行迭代。所以如果在实际执行前,集合数据发生改变会导致结果集和预期不符。
  4. 对于Linq to object,当集合对象是 IEnumerable 时,对单个对象进行迭代的方式是:先把单个对象走完所有的Linq方法后,直到最后或者执行到返回值不是IEnumerable的Linq方法(该方法会被执行),才会迭代下一个对象。 如果Linq方法的返回值不是IEnumerable,单个对象的迭代会到该方法(含)为止,会立即进行下一个对象的迭代。所有的对象迭代完毕后,会有一个临时的结果集(非IEnumerable),然后把这个结果集重复前面的步骤,直至结束。 OrderBy()的返回值是IOrderedEnumerable,所以运行了OrderBy()后,单个对象的迭代就会结束,继续下一个对象的迭代。,然后把这个暂存结果集执行OrderBy()后面的Linq方法。
  5. 4 的基础上,对于IEnumerable,如果有多个条件,我们可以写在同一个Where()里,也可以拆开写在多个Where()里,不会影响效率的,因为不会生成多个暂存结果集。
  6. IEnumerable.AsQueryable().AsEnumerable()是没问题的,遵循IEnumerable的正常流程:断点不会转移,仍然是延迟执行。

操作步骤

有2种方法:

  • 光标移动到箭头=>后面的lambda语句(方法体)内,按F9,这个lambda语句的断点就打上了。其他的lambda语句操作类似。
  • 右键单击其中一个lambda语句(方法体)内的任意位置,然后选择“断点 - >插入断点”。断点就打在这个lambda表达式上了。

上面的2种方法,都是要把位置选在lambda语句内,因为这个语句才是方法体,必须要定位到方法体内才行!否则还是打在外面了!

断点的高级用法

打断点后,我们可以对断点进行设置,可以达到2个目的:

  1. 满足条件才触发断点(条件断点
  2. 触发断点后,输出当前的数据(断点操作
操作步骤

鼠标放在断点的小红点上,会出现浮动块,点击里面的齿轮,我们可以在里面设置条件操作(可以同时勾选设置)。

  • 条件:满足条件才触发断点
  • 操作:触发断点后,输出当前的数据
条件 (条件断点)

勾上条件,会出现设置框,有3个框。 前2个框可以点开看看一些选择项,第3个框可以输入一些代码,代码里可以使用变量/方法,会有智能提示的。

注意:lambda表达式的参数没有提示,需要手动输入参数名和参数的属性/方法

设置好后,只有满足设置的条件,才会触发断点。

操作 (断点操作)

勾上操作,会出现输入框和勾选框。

我们可以在输入框里输入一些字符串,字符串里可以使用变量/有返回值的方法,不过它们必须要放在 {} 里,会有智能提示的。

注意:lambda表达式的参数没有提示,需要手动输入参数名和参数的属性/方法。如果想输出{},需要转义\{;如果想输出\,需要转义\\

另外,还可以使用一些特殊关键字,具体的可以把鼠标放在输入框右侧的 叹号! 上,会有提示的。

接下来说一下勾选框(继续执行),它默认是勾选的:

  • 勾选:当触发断点并输出数据后,程序不会停下来,会继续执行后面的代码;并且断点的小红点会变成菱形
  • 不勾选:当触发断点并输出数据后,程序停下来

设置好后,当断点触发时,会在输出窗口里输出数据的。不过输出窗口里会有其他信息,此时需要我们慢慢找数据了。。。

如果集合是IQueryable,在lambda表达式里打上断点和设置操作,操作会输出错误:order name: id=error CS0103: 当前上下文中不存在名称“p”, name=error CS0103: 当前上下文中不存在名称“p”

注意

  1. 不能调试LINQ to SQL,因为LINQ to SQL是翻译成sql语句了。具体见单步执行和 LINQ
  2. 由于要对单个Linq语句打断点,建议每个Linq语句都放在单独的一行,这样也清晰易读。 Robot tmpRobot01 = robots .Where(p => p.Id == miku001.Id) .OrderBy(p => p.Name) .FirstOrDefault();

疑问

如果Linq里没有lambda表达式,打断点就打在了整个语句上,而不是单个Linq上。是这个原因吗?

参考

  1. 如何在C#中调试LINQ查询:https://michaelscodingspot.com/debug-linq-in-csharp/
  2. C#中的条件断点:https://www.c-sharpcorner.com/UploadFile/b1df45/conditional-breakpoints-in-C-Sharp/
  3. 调试 LINQ:https://docs.microsoft.com/zh-cn/visualstudio/debugger/debugging-linq?view=vs-2019

VS插件OzCode

VS插件OzCode的功能强大,简单易用,可是是收费的。不过OzCode对MVP和开源贡献者是免费的,这就需要努力了。

我没使用过,暂时放几个链接:

  1. 2017年调试LINQ:LINQPad与OzCode:https://oz-code.com/blog/debugging-linq-available-tool-comparison/
  2. 如何在C#中调试LINQ查询:https://michaelscodingspot.com/debug-linq-in-csharp/
  3. Vs 调试插件 —OzCode 特性讲解+破解工具和教程:https://blog.csdn.net/sky__god/article/details/86153982

LinqPad

这个软件很强大,可以执行代码片段,当然也可以执行Linq了。我几乎不用,暂时放几个链接:

  1. 2017年调试LINQ:LINQPad与OzCode:https://oz-code.com/blog/debugging-linq-available-tool-comparison/
  2. 如何在C#中调试LINQ查询:https://michaelscodingspot.com/debug-linq-in-csharp/

扩展

如何知道每一步链式调用的结果

如何知道每一步链式调用的结果?如何知道每一句Linq执行的结果?

有4种方法:

  1. VS里使用【快速监视】
  2. VS里使用断点设置里的【操作】
  3. 使用OzCode
  4. 使用LinqPad
VS里使用【快速监视】

首先在整个语句上设置断点,当程序运行到该断点时,在集合对象上右键->快速监视,然后把想知道结果的整个代码复制到表达式文本框里,点击右侧的重新计算,就能知道这步链式调用的结果了。

注意
  1. 只有把断点设在整个语句上才能监视到。不能设置在lambda表达式上。 因为lambda表达式是被编译成了一个方法,断点在这个方法里。运行到该断点时,上下文是这个方法的上下文,只能访问到该方法内部变量,是不能访问到外部对象的!
  2. 该方式只能适用于返回结果较少的情况,如果返回结果很多,估计会出问题。某人说:vs没事儿给你抽个风,整个调试器都直接挂,必须重启调试才能继续
图示
VS里使用断点设置里的【操作】

这种方式里的断点是设置在lambda表达式上,和前面的VS里使用【快速监视】 里的断点位置不一样!!!

把断点设置在lambda表达式上,然后在断点设置里添加条件和操作。

  • 条件必须和lambda表达式一模一样,否则数据就不同了,建议直接把lambda表达式复制进去。
  • 操作里输出有用的简单的信息。

详细的操作步骤见前面的断点的高级用法

不填条件的偷懒法

由于每个断点设置里的条件都要把lambda表达式复制进去,十分麻烦,推荐一个简单的方法:

每个Linq语句的结果让下一个Linq语句输出,下一个Linq语句不要设置条件,只设置操作。(因为只有当前Linq语句满足条件后,才会进入下一个Linq语句。)

不过如果只有一个Linq语句或者是最后一个Linq语句,这种偷懒方式就不行了,这时候我们只有1种选择:再加一个Linq语句(OrderBy...),让它来输出。

其实还有一种选择:在断点里添加条件。不过这种选择只适用于只有一个Linq语句的情况。是最后一个Linq语句时是不行的!因为最后一个Linq语句输出的是上一条Linq语句的信息的,如果添加了条件,输出的就是当前Linq语句的信息了,那上一条Linq语句的信息由谁来输出?

注意
  1. 该方式只能适用于返回结果较少的情况,如果返回结果很多,输出窗口估计能翻好几页吧,那就难受了。。
图示

下图是不填条件偷懒法每个Linq语句的结果让下一个Linq语句输出,下一个Linq语句不要设置条件,只设置操作。所以图中是 OrderBy输出Where的执行结果

使用OzCode

VS插件OzCode很强大,每一个Linq语句的执行结果都能统计并展示出来,详情参考:如何在C#中调试LINQ查询如何在C#中调试LINQ查询

使用LinqPad

LinqPad软件很强大,不过数据源是个问题,操作步骤参考:如何在C#中调试LINQ查询如何在C#中调试LINQ查询

参考

  1. 2017年调试LINQ:LINQPad与OzCode:https://oz-code.com/blog/debugging-linq-available-tool-comparison/
  2. 如何在C#中调试LINQ查询:https://michaelscodingspot.com/debug-linq-in-csharp/
  3. C#中的条件断点:https://www.c-sharpcorner.com/UploadFile/b1df45/conditional-breakpoints-in-C-Sharp/
  4. 调试 LINQ:https://docs.microsoft.com/zh-cn/visualstudio/debugger/debugging-linq?view=vs-2019

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
金三银四面试:C#.NET面试题中高级篇5-Linq和EF
实体框架EF是http://ADO.NET中的一组支持开发面向数据的软件应用程序的技术,是微软的一个ORM框架。
郑子铭
2022/04/19
4.2K0
.NET中数据访问方式(一):LINQ
语言集成查询(Language-Integrated Query),简称LINQ,.NET中的LINQ体系如下图所示:
雪飞鸿
2018/09/05
2.7K0
.NET中数据访问方式(一):LINQ
Linq基础知识小记二
书写Linq查询有两种方法,第一种是通过方法语法(也就是扩展方法),第二种是查询表达式语法. 1、方法语法 方法语法就是通过扩展方法和Lambda表达式来创建查询 (1)、链式查询 这种查询方式很多语言都支持,通过一段实例,介绍Linq的链式查询.需求如下:找出字符串数组中含有字母e的字符穿,并按长度排序,最后将结果转为大写.代码如下: string[] names = {"James","Kobe","Curry","Durrent" }; IEnumerable<string> result = nam
郑小超.
2018/01/26
1.3K0
.net 温故知新:【6】Linq是什么
这段代码使用Linq对List列表进行筛选、分组、排序等一系列操作展示了Linq的强大和便捷,那么我们为什么需要学习Linq?可以看到这样一堆逻辑只几行Linq很快就可以实现,如果要我们自己实现方法去处理这个List肯定是比较繁琐的。 Linq是什么?如下是官方文档对于Linq的描述:
SpringSun
2022/09/16
2.7K0
.net 温故知新:【6】Linq是什么
30分钟LINQ教程
      也就是说,在声明一个变量(并且同时给它赋值)的时候,完全不用指定变量的类型,只要一个var就解决问题了
liulun
2022/05/09
8130
用linqPad帮助你快速学习LINQ
在这里我向大家推荐的一个具是LinqPad有了这个工具并熟练使用就可以很快学习并掌握linq linqPad下载地址:http://www.linqpad.net/ 它也自带了很多例子方便大家查询,linqPad支持object ,xml,sql ,  to linq这里我只讲一下sql to linq 好多同学不知道怎么用linq完成 left join ,inner join 等,这里我就用这个工具给大家实现一下 linqpad 会给我们同时生成lambda表达式,sql和IL 我一般情况下有linq的
lpxxn
2018/01/31
1.3K0
用linqPad帮助你快速学习LINQ
LINQ常用扩展方法、委托、Lambda、yield
 每一项数据都会经过predicate的测试,如果针对一个元素,predicate执行的返回值为true,那么这个元素就会放到返回值中。 Where参数是一个lambda表达式格式的匿名方法,方法的参数e表示当前判断的元素对象。参数的名字不一定非要叫e,不过一般lambda表达式中的变量名长度都不长。
鱼找水需要时间
2024/03/23
1140
C#规范整理·集合和Linq
LINQ(Language Integrated Query,语言集成查询)提供了类似于SQL的语法,能对集合进行遍历、筛选和投影。一旦掌握了LINQ,你就会发现在开发中再也离不开它。
郑子铭
2023/08/30
2410
C#规范整理·集合和Linq
.NET面试题系列[15] - LINQ:性能
当你使用LINQ to SQL时,请使用工具(比如LINQPad)查看系统生成的SQL语句,这会帮你发现问题可能发生在何处。
s055523
2018/09/14
2.6K0
.NET面试题系列[15] - LINQ:性能
linq中order by 和group by (含lambda表达式实现)以及综合案例
linq的语法通过System.Linq下面的Enumerable类提供支持,也就是说,只要是实现了IEnumerable<T>的对象都可以使用Linq的语法来查询。LINQ定义了大约40个查询操作符,如select、from、in、where、group by 以及order by,通过查看源代码,实际上linq为IEnumerable<TSource>实现了一系列的扩展方法。
yaphetsfang
2020/07/30
3.6K0
linq中order by 和group by (含lambda表达式实现)以及综合案例
C# 基础知识系列- 6 Lambda表达式和Linq简单介绍
C#的lambda和Linq可以说是一大亮点,C#的Lambda无处不在,Linq在数据查询上也有着举足轻重的地位。
程序员小高
2020/04/29
1.4K0
.NET面试题系列[14] - LINQ to SQL与IQueryable
"理解IQueryable的最简单方式就是,把它看作一个查询,在执行的时候,将会生成结果序列。" - Jon Skeet
s055523
2018/09/14
1.7K0
.NET面试题系列[14] - LINQ to SQL与IQueryable
LINQ之方法语法
上节讲到使用linq的查询关键字进行查询,这节讲一下linq查询的另一种方式——linq方法。
宿春磊Charles
2022/03/29
1K0
LINQ初步
语言集查询(Language Integrated Query, LINQ)集成了C#编程语言中的查询语法,可以用同样的语法访问不同的数据源。LINQ提供了不同数据源的抽象层,可以使用相同的语法。
卡尔曼和玻尔兹曼谁曼
2019/01/25
1.7K0
LINQ初步
[C#] 走进 LINQ 的世界
    技巧:《Linq To Objects – 如何操作字符串》 和 《Linq To Objects – 如何操作文件目录》
全栈程序员站长
2022/09/06
4.6K0
[C#] 走进 LINQ 的世界
.NET深入解析LINQ框架(三:LINQ优雅的前奏)
在上述代码中的“(1)重点”的地方,我们很清楚的看见表达式树被动态编译后然后紧接着又被执行,这里就能看出为什么IEnumerable<T>对象需要能够被转换成IQueryable<T>对象。这样就可以消除IEnumerable<T>、IQueryable<T>这两个接口之间的动态查询瓶颈。
王清培
2019/03/01
1.7K0
.NET深入解析LINQ框架(三:LINQ优雅的前奏)
C#内建接口:IQueryable
IQueryable是 IEnumerable 接口的子接口,相比之下提供了更丰富的查询功能。其主要用于 LINQ(Language Integrated Query)查询,它允许我们在编写类型安全的查询表达式时,将查询操作推迟到实际执行查询的时候,以便进行更有效的查询优化。
宿春磊Charles
2023/09/08
3230
.NET深入解析LINQ框架(四:IQueryable、IQueryProvider接口详解)
在开始看本篇文章之前先允许我打断一下各位的兴致。其实这篇文章本来是没有打算加“开篇介绍”这一小节的,后来想想还是有必要反馈一下读者的意见。经过前三篇文章的详细讲解,我们基本上对LINQ框架的构成原理有了一个根本的认识,包括对它的设计模型、对象的模型等,知道LINQ的查询表达式其实是C#之上的语法糖,不过这个糖确实不错,很方便很及时,又对一系列的LINQ支撑原理进行了大片理论的介绍,不知道效果如何;
王清培
2019/03/01
1.5K0
.NET深入解析LINQ框架(四:IQueryable、IQueryProvider接口详解)
LINQ基础概述
介绍LINQ基础之前,首说一下LINQ 的历史和LINQ是什么,然后说一下学习 LINQ要了解的东西和 LINQ基础语法 LINQ 的历史 从语言方面的进化 –委托 –匿名方法 –Lambda表达式 –Linq查询表达式 上边这四个我会在下边一一解说 从时间方面的演进 –2004年 –2005年9月,C#2.0的PDC上发布 –2005年11月,C#2.0预览版 –2006年1月,VB8.0预览版 –2007年11月,.net 3.5发布 LINQ是什么 LINQ是语言级集成查询(Lan
lpxxn
2018/01/31
1.8K0
LINQ基础概述
编写高质量代码改善C#程序的157个建议[IEnumerable<T>和IQueryable<T>、LINQ避免迭代、LINQ替代迭代]
本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html 。本文主要学习记录以下内容:
aehyok
2018/08/31
9650
编写高质量代码改善C#程序的157个建议[IEnumerable<T>和IQueryable<T>、LINQ避免迭代、LINQ替代迭代]
相关推荐
金三银四面试:C#.NET面试题中高级篇5-Linq和EF
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文