来源:https://note.guoqianfan.com/2021/03/21/debug-linq-with-vs/
Linq调试有3种方法,准确来说是2种,因为LinqPad算是复制代码段到外部了。。
在VS里,是可以对Linq调试的,不过一般打断点都会打在整个语句上,这时候我们要换个打法,把断点打在lambda表达式上。
IEnumerable
时,才能命中到Linq里的lambda表达式,IQueryable
是不行的。如果是IQueryable
,此时就算在lambda表达式里打上断点,在代码执行时,断点会向上转移到整个语句上。
如果是IQueryable
,在lambda表达式里打上断点和设置操作,操作会输出错误:order name: id=error CS0103: 当前上下文中不存在名称“p”, name=error CS0103: 当前上下文中不存在名称“p”
。IEnumerable
时,是延迟执行的。只有结果被用到时,才会进行迭代。所以如果在实际执行前,集合数据发生改变会导致结果集和预期不符。IEnumerable
时,对单个对象进行迭代的方式是:先把单个对象走完所有的Linq方法后,直到最后或者执行到返回值不是IEnumerable
的Linq方法(该方法会被执行),才会迭代下一个对象。
如果Linq方法的返回值不是IEnumerable
,单个对象的迭代会到该方法(含)为止,会立即进行下一个对象的迭代。所有的对象迭代完毕后,会有一个临时的结果集(非IEnumerable
),然后把这个结果集重复前面的步骤,直至结束。
OrderBy()
的返回值是IOrderedEnumerable
,所以运行了OrderBy()
后,单个对象的迭代就会结束,继续下一个对象的迭代。,然后把这个暂存结果集执行OrderBy()
后面的Linq方法。IEnumerable
,如果有多个条件,我们可以写在同一个Where()
里,也可以拆开写在多个Where()
里,不会影响效率的,因为不会生成多个暂存结果集。IEnumerable.AsQueryable().AsEnumerable()
是没问题的,遵循IEnumerable
的正常流程:断点不会转移,仍然是延迟执行。有2种方法:
=>
后面的lambda语句(方法体)内,按F9
,这个lambda语句的断点就打上了。其他的lambda语句操作类似。上面的2种方法,都是要把位置选在lambda语句内,因为这个语句才是方法体,必须要定位到方法体内才行!否则还是打在外面了!
打断点后,我们可以对断点进行设置,可以达到2个目的:
鼠标放在断点的小红点上,会出现浮动块,点击里面的齿轮,我们可以在里面设置条件和操作(可以同时勾选设置)。
勾上条件,会出现设置框,有3个框。 前2个框可以点开看看一些选择项,第3个框可以输入一些代码,代码里可以使用变量/方法,会有智能提示的。
注意:lambda表达式的参数没有提示,需要手动输入参数名和参数的属性/方法。
设置好后,只有满足设置的条件,才会触发断点。
勾上操作,会出现输入框和勾选框。
我们可以在输入框里输入一些字符串,字符串里可以使用变量/有返回值的方法,不过它们必须要放在 {}
里,会有智能提示的。
注意:lambda表达式的参数没有提示,需要手动输入参数名和参数的属性/方法。如果想输出{}
,需要转义\{
;如果想输出\
,需要转义\\
。
另外,还可以使用一些特殊关键字,具体的可以把鼠标放在输入框右侧的 叹号!
上,会有提示的。
接下来说一下勾选框(继续执行),它默认是勾选的:
设置好后,当断点触发时,会在输出窗口里输出数据的。不过输出窗口里会有其他信息,此时需要我们慢慢找数据了。。。
如果集合是IQueryable
,在lambda表达式里打上断点和设置操作,操作会输出错误:order name: id=error CS0103: 当前上下文中不存在名称“p”, name=error CS0103: 当前上下文中不存在名称“p”
。
如果Linq里没有lambda表达式,打断点就打在了整个语句上,而不是单个Linq上。是这个原因吗?
VS插件OzCode的功能强大,简单易用,可是是收费的。不过OzCode对MVP和开源贡献者是免费的,这就需要努力了。
我没使用过,暂时放几个链接:
这个软件很强大,可以执行代码片段,当然也可以执行Linq了。我几乎不用,暂时放几个链接:
如何知道每一步链式调用的结果?如何知道每一句Linq执行的结果?
有4种方法:
首先在整个语句上设置断点,当程序运行到该断点时,在集合对象上右键
->快速监视
,然后把想知道结果的整个代码复制到表达式文本框
里,点击右侧的重新计算
,就能知道这步链式调用的结果了。
vs没事儿给你抽个风,整个调试器都直接挂,必须重启调试才能继续
这种方式里的断点是设置在lambda表达式上,和前面的VS里使用【快速监视】 里的断点位置不一样!!!
把断点设置在lambda表达式上,然后在断点设置里添加条件和操作。
详细的操作步骤见前面的断点的高级用法
由于每个断点设置里的条件都要把lambda表达式复制进去,十分麻烦,推荐一个简单的方法:
每个Linq语句的结果让下一个Linq语句输出,下一个Linq语句不要设置条件,只设置操作。(因为只有当前Linq语句满足条件后,才会进入下一个Linq语句。)
不过如果只有一个Linq语句或者是最后一个Linq语句,这种偷懒方式就不行了,这时候我们只有1种选择:再加一个Linq语句(OrderBy...
),让它来输出。
其实还有一种选择:在断点里添加条件。不过这种选择只适用于只有一个Linq语句的情况。是最后一个Linq语句时是不行的!因为最后一个Linq语句输出的是上一条Linq语句的信息的,如果添加了条件,输出的就是当前Linq语句的信息了,那上一条Linq语句的信息由谁来输出?
下图是不填条件偷懒法:每个Linq语句的结果让下一个Linq语句输出,下一个Linq语句不要设置条件,只设置操作。所以图中是 OrderBy
输出Where
的执行结果。
VS插件OzCode很强大,每一个Linq语句的执行结果都能统计并展示出来,详情参考:如何在C#中调试LINQ查询 和 如何在C#中调试LINQ查询
LinqPad软件很强大,不过数据源是个问题,操作步骤参考:如何在C#中调试LINQ查询 和 如何在C#中调试LINQ查询
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有