簡體   English   中英

為什么以下C#代碼在可空的DateTime初始化時拋出NullReferenceException?

[英]Why the following C# code throws NullReferenceException on nullable DateTime initialization?

這是一些簡單的代碼:

    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:

這是在聲明捕獲的變量范圍的上下文中移動執行點的副作用。 將其報告為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 ”。

嗯......真的很奇怪。 你有引用中的mscorlib和使用中的系統嗎? 也許你有一個名為DateTime的另一個類,它會覆蓋System.DateTime。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM