代码之家  ›  专栏  ›  技术社区  ›  Max

为什么不可能在即时窗口中评估lambdas?

  •  20
  • Max  · 技术社区  · 14 年前

    有什么特别的原因吗?是根本不可能,还是只是还没有实现?可能有任何第三方加载项允许lambda计算?

    更新:

    我在codeplex上找到了这个项目 Extended Immediate Window . 似乎它已经被抛弃了一段时间,但这可以作为一个概念的证明。有人知道其他即时窗口扩展插件吗?例如,可以在C中为/foreach语句运行的语句?

    5 回复  |  直到 6 年前
        1
  •  15
  •   Community Mofi    7 年前

    JaredPar 微软的一些博客文章回答了你的问题: part 1 part 2 . 你可以在那里找到答案。

        2
  •  5
  •   Marc Gravell    14 年前

    在写lambda时,捕捉变量的动作。 明显地 改变底层代码的结构(将变量移动到编译器生成的类的字段中,这些类本身很容易被链接到闭包上下文中)。

    甚至不考虑将军 复杂性 这样做,它将有两个选择:

    • 将所有变量值捕获为常量;可行且非常简单,但很容易意味着在即时窗口中执行的结果是 非常 与在主体中执行的结果不同(非常不理想)
    • 动态重写整个代码(基于上述原因)(猜测,不可能)

    如果在“不受欢迎”和“不可能”之间做出选择,我 猜测 他们只是选择不实现固有的脆弱特性, 写起来很复杂。

        3
  •  4
  •   Phyx    14 年前

    我认为这是因为即时窗口只能计算表达式,或者更确切地说,它只能进行调用和赋值。要计算lambda表达式,必须为该lambda创建一个闭包,然后执行typechecked。

    我认为归根结底,即时窗口只是一个评价者,而不是一个口译员。

    http://msdn.microsoft.com/en-us/library/f177hahy(VS.80).aspx

    “即时窗口在设计时用于调试和评估表达式、执行语句、打印变量值等。它允许您输入要在调试期间由开发语言计算或执行的表达式。”

    所以实际上,你的问题归结为为什么你不能在即时窗口中定义函数(因为lambda只是一个无意义的函数),我想答案是它根本不是为这个而设计的。

        4
  •  1
  •   user8128167    9 年前

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

        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;
        }
    

    在这里,我一直得到以下错误,所以我想打印出各种存储库中的所有项目:

    InnerException  {"The DELETE statement conflicted with the REFERENCE constraint \"FK_dbo.Department_dbo.RoleHierarchy_OranizationalRoleId\". The conflict occurred in database \"CC_Portal_SchoolObjectModel\", table \"dbo.Department\", column 'OranizationalRoleId'.\r\nThe statement has been terminated."} System.Exception {System.Data.SqlClient.SqlException}
    

    然后,我通过在即时窗口中执行以下操作来了解部门存储库中有多少记录:

    _unitOfWork.DepartmentRepository.GetAll().ToList().Count
    

    返回243。

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

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

    这个想法的作者可以在这里找到: http://ogresoft.blogspot.ca/2013/06/how-to-write-loop-or-lambda-expression.html

        5
  •  -1
  •   Aggelos Biboudis    14 年前

    我假设,因为它是懒惰的评估,所以即时窗口不能预先知道捕获的变量(闭包)应该具有什么值。