C# Visual Studio调试“;“快速观察”;工具和lambda表达式

C# Visual Studio调试“;“快速观察”;工具和lambda表达式,c#,visual-studio,debugging,lambda,C#,Visual Studio,Debugging,Lambda,为什么在“快速观察”窗口中调试时不能使用lambda表达式 UPD:另见 调试器的表达式计算器不支持Lambda表达式。。。这并不奇怪,因为在编译时,它们被用来创建方法(或表达式树)而不是表达式(在Reflector中查看,显示切换到.NET2以查看它们) 当然,它们还可以形成一个闭包,另一个完整的结构层。Lambda表达式和匿名方法一样,实际上非常复杂。即使我们排除了表达式(.NET3.5),仍然会留下很多复杂性,尤其是捕获的变量,这些变量从根本上重新构造了使用它们的代码(您认为的变量会成为

为什么在“快速观察”窗口中调试时不能使用lambda表达式

UPD:另见


调试器的表达式计算器不支持Lambda表达式。。。这并不奇怪,因为在编译时,它们被用来创建方法(或表达式树)而不是表达式(在Reflector中查看,显示切换到.NET2以查看它们)


当然,它们还可以形成一个闭包,另一个完整的结构层。

Lambda表达式和匿名方法一样,实际上非常复杂。即使我们排除了
表达式
(.NET3.5),仍然会留下很多复杂性,尤其是捕获的变量,这些变量从根本上重新构造了使用它们的代码(您认为的变量会成为编译器生成类上的字段),并带有一些烟雾和镜像


因此,我一点也不奇怪您不能无所事事地使用它们——有大量的编译器工作(以及幕后的类型生成)支持这种魔力。

不,您不能在watch/locals/immediate窗口中使用lambda表达式。正如马克所指出的,这是一个极其复杂的问题。不过,我想深入探讨一下这个话题

<> P>在调试器中执行匿名函数的大多数人认为,它不会出现在VaCuUM中。定义和运行匿名函数的行为会改变代码库的底层结构。通常,尤其是从即时窗口更改代码是一项非常困难的任务

考虑以下代码

void Example() {
  var v1 = 42;
  var v2 = 56; 
  Func<int> func1 = () => v1;
  System.Diagnostics.Debugger.Break();
  var v3 = v1 + v2;
}
如果函数示例在调试器中运行,它将在换行处停止。现在想象一下,如果用户在“监视”窗口中键入以下内容

(Func<int>)(() => v2);
然而,要在代码中真正获得这种效果,EE需要更改最后一行代码,这实际上是一个ENC操作。虽然这个特定的例子是可能的,但大部分场景都是不可能的

更糟糕的是,执行lambda表达式时不应创建新的闭包。它实际上应该将数据附加到原始闭包中。在这一点上,您将直接进入限制ENC

不幸的是,我的小例子只触及了我们遇到的问题的表面。我一直说我会就这个话题写一篇完整的博客,希望这个周末我有时间

这可能会有帮助: Visual Studio的扩展即时窗口(在调试中使用Linq、Lambda Expr)

祝你一切顺利,
Patrick

您不能在即时窗口或监视窗口中使用lambda表达式


但是,您可以使用,它的形式为。Where(“Id=@0”,2)-它没有标准Linq中可用的全部方法,也没有lambda表达式的全部功能,但仍然比没有好

为了回答您的问题,这里是Visual Studio项目经理对您为什么不能这样做的官方解释。简而言之,因为在VS中实现“真的很难”,但该功能目前正在开发中(2014年8月更新)

当你在那里时,添加你的投票

未来来了

(写作时预览)


表达式计算器必须重写,因此缺少许多功能:远程调试ASP.NET、在即时窗口中声明变量、检查动态变量等。此外,目前不支持需要调用本机函数的lambda表达式。

如果您仍然需要使用Visual Studio 2013,您实际上可以编写一个循环,或立即窗口中的lambda表达式,同时使用package manager控制台窗口。在我的例子中,我在函数顶部添加了一个列表:

private void RemoveRoleHierarchy()
{
    #if DEBUG
    var departments = _unitOfWork.DepartmentRepository.GetAll().ToList();
    var roleHierarchies = _unitOfWork.RoleHierarchyRepository.GetAll().ToList();
    #endif

    try
    {
        //RoleHierarchy
        foreach (SchoolBo.RoleHierarchy item in _listSoRoleHierarchy.Where(r => r.BusinessKeyMatched == false))
            _unitOfWork.RoleHierarchyRepository.Remove(item.Id);

        _unitOfWork.Save();
    }
    catch (Exception e)
    {
        Debug.WriteLine(e.ToString());
        throw;
    }
}
其中我的
GetAll()
函数是:

private DbSet<T> _dbSet;

public virtual IList<T> GetAll()
{
    List<T> list;
    IQueryable<T> dbQuery = _dbSet;
    list = dbQuery
        .ToList<T>();

    return list;
}
返回243

因此,如果在package manager控制台中执行以下操作,它将打印出所有项目:

PM> for($i = 0; $i -lt 243; $i++) { $a = $dte.Debugger.GetExpression("departments[$i].OrgagnizationalRoleId"); Write-Host $a.Value $i }

这个想法的作者可以在VS 2015中找到,你现在可以这样做了,这是他们添加的新功能之一。

好吧,他们可能会创建方法;他们可能会创建
Expression
树-这取决于上下文。请注意,虽然第一个链接看起来很棒,但它是alpha链接,不太可能从中产生(上次更新于2008年)。呜呜,呜呜,接受平庸,呜呜,呜呜。调试器是IDE的核心,而你破坏了它!手表窗口中的lambda不需要捕获任何东西。与任何其他监视代码一样,它们仅在特定的堆栈帧上才有意义。(或者捕获变量,移动到另一个具有相同变量名的函数……还有什么?)调试器的目的是绕过编译器。让它工作吧!为什么他们不允许在监视窗口的lambdas上捕获变量。简单且允许一系列调试场景,其中lambda仅用于真正的功能代码中。@LuizFelipe即使这仍然是一个巨大的挑战。它要求EE实际生成回调的完整函数体(一直到IL)。EE今天并没有做这种事情,相反,它是一个翻译。@JaredPar你能分享一下marc的博客文章吗。。。虽然其他人解释说这是不可能的,但这至少为我们提供了一个可能的解决方案+1为了澄清这一点,您可以“导入System.Linq.Dynamic”,然后在调试窗口中编写“Where(something.AsQueryable,“property>xyz”,nothing)”,这非常好。即使您没有获得完整的Linq扩展方法,例如,没有
。任何(字符串谓词)
,您也可以将类似于:
.Where(“Id>2”)。任何()
在Watch(观察)窗口中,或锁定到源代码。太棒了!这已经完成,并在VS 2015预览版中提供。我尝试了MSDN上针对lambda expression给出的非常简单的示例,但不起作用。我有VS 2015 enterpriseedition@Franciscod“Anconia在调试中启用lambda支持,”使用Man
private DbSet<T> _dbSet;

public virtual IList<T> GetAll()
{
    List<T> list;
    IQueryable<T> dbQuery = _dbSet;
    list = dbQuery
        .ToList<T>();

    return list;
}
_unitOfWork.DepartmentRepository.GetAll().ToList().Count
PM> for($i = 0; $i -lt 243; $i++) { $a = $dte.Debugger.GetExpression("departments[$i].OrgagnizationalRoleId"); Write-Host $a.Value $i }