4

这是一些简单的代码:

    static void Main(string[] args)
    {
        var coll = new List<string> {"test", "test2", "test3"};

        var filteredColl = coll.Select(x => x).ToList();

        if (!filteredColl.Any())
        {
            DateTime? date = new DateTime();

            filteredColl = coll.Where(x => date.GetValueOrDefault().Date.ToString(CultureInfo.InvariantCulture) == x).Select(x => x).ToList();
        }
    }

问题是,为什么以下步骤会导致 NullReferenceException 崩溃

1) if 的断点

断点

2)设置下一个执行点:

执行点

3)尝试继续F10:

例外

如果我注释掉代码的最后一行,它就不会崩溃。

更新:这是堆栈跟踪:

System.NullReferenceException was unhandled   HResult=-2147467261  
Message=Object reference not set to an instance of an object.  
Source=ConsoleApplication28   StackTrace:
       at ConsoleApplication28.Program.Main(String[] args) in Program.cs: line 21
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()   InnerException:
4

2 回答 2

11

这是在声明捕获的变量范围的上下文中移动执行点的副作用。将其报告为 IDE 错误是合理的,但修复它并非易事。基本上,date它不是一个变量——它是捕获上下文中的一个字段,因为 lambda。编译器本质上是:

if (!filteredColl.Any())
{
    var ctx = new SomeCaptureContext(); // <== invented by the compiler
    ctx.date = new DateTime();

    filteredColl = coll.Where(ctx.SomePredicate).Select(x => x).ToList();
}

哪里SomePredicate是:

class SomeCaptureContext {
    public DateTime? date; // yes, a public field - needs to support 'ref' etc
    public bool SomePredicate(string x) // the actual name is horrible
    {
        return this.date.GetValueOrDefault()
              .Date.ToString(CultureInfo.InvariantCulture) == x;
    }
}

这里的问题是当你将执行位置拖到:

DateTime? date = new DateTime();

实际上(在 IL 术语中)将其拖到该行:

ctx.date = new DateTime();

紧接在此之前的捕获上下文行,即

var ctx = new SomeCaptureContext();

从未被处决,所以ctxnull。因此NullReferenceException.

将此记录为错误是合理的,但它是一个微妙的错误 - 您不一定总是希望拖动执行上下文来初始化捕获上下文 - 它必须是“如果它们是null”。

于 2013-09-13T08:31:07.783 回答
0

嗯……真的很奇怪。您在引用中有 mscorlib,在使用中有 System 吗?也许您有另一个名为 DateTime 的类,它覆盖了 System.DateTime。

于 2013-09-13T08:18:52.490 回答