【发布时间】:2014-08-04 14:10:59
【问题描述】:
以如下代码为例:
if (true)
{
string foo = null;
List<string> bar = new List<string>
{
"test"
};
bar.Any(t => t == foo);
}
如果我以常规方式运行该程序(没有断点或任何其他中断),则一切正常,没有异常或错误(如您所料)。
现在,如果我在 if 语句上放置一个断点并将光标移动到大括号,如下图所示(使用我的鼠标,而不是使用 F10,因此跳过 if(true) 语句):
当调试器执行string foo = null 语句时,我得到了System.NullReferenceException 类型的异常
这似乎与foo 变量在if 语句内的lambda 表达式中使用的事实有关。我已经在 Visual Studio 2012 和 2013(专业版和终极版)上测试并复制了它。
知道为什么会发生这种情况吗?
【问题讨论】:
-
您应该检查生成 IL,但很可能您的变量被捕获到创建的类中以获取 lambda 表达式所需的闭包,并且该类实例尚不存在(或者您在跳过时跳过了它的初始化
if(true)检查。 -
无法验证,但是当您跳过
if语句时,这看起来像foo被提升到的底层对象(因为它被 lambda 捕获)没有被分配. -
当你说它似乎与变量 foo 在 lambda 中使用这一事实有关时,这是否意味着如果你以后使用 foo 它停止失败?但这一切似乎都很奇怪,因为它不应该真的在简单的分配上抛出异常......
-
@Chris “简单”赋值并不是那么简单:它秘密地赋值给一个只有编译器可访问类型的隐藏对象的字段。其实很复杂!
-
另一个观察结果(证实了“隐藏对象未分配”理论):如果将
foo的声明移到if语句之外,错误就会消失,可能是因为我们现在需要在if语句之前分配对象。似乎这些对象的所有块级分配都与 if 语句相关联,至少就调试器所知而言。一如既往的教训:C# 中的闭包没有什么“简单”的。
标签: c# lambda visual-studio-debugging