I am stepping through a .NET Core 3.1 service and the code is blowing up with a null exception on the following line:
DateTime maxOwnerValidDate = DateTime.UtcNow;
The exception is:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
maxOwnerValidDate._dateData was null.
After researching _dateData, I found that this is something introduced by .NET 6, 7. I did recently update the environment on this machine to .NET 6. Interestingly, the above statement does not throw any exceptions if placed elsewhere in the code. It is only failing when the statement exists inside of an asynch Task.
At this point, I am not interested in upgrading this .NET Core project to .NET6/7 (yet). I’m just debugging something else.
Does anyone have any idea what I’m doing wrong? How can I get the code to continue to function here without rolling back the .NET6 install or working from another environment?
The inner workings of the new DateTime object and the new private ulong _dateData property and why it would be null inside a new DateTime object declared inside an asnych Task are so far beyond my skill set that I have nothing to lean on.
VS break on exception screen cap
ADDITIONS:
I have found that it is in fact related to pushing through the code by manually moving the step pointer in Visual Studio. In some cases there is no impact. Here there is a very repeatable, very specific, very odd failure.
Sample code to recreate:
public async Task ProcessWorkflow(List<Object> steps)
{
foreach (Object step in steps)
{
bool pushingForward = true; //<<< Breakpoint 1 here <<<
DateTime maxOwnerValidDate = DateTime.UtcNow; //Manually push through to here and step forward (F10)
bool success = await ProcessWorkflowSteps(step); //Success: maxOwnerValidDate populated, no exception thrown.
}
}
public async Task<bool> ProcessWorkflowSteps(Object step)
{
List<int> someStuff = new List<int>() { 1, 2, 4, 5 };
bool thisShouldRun = false;
if (thisShouldRun) //<<< Breakpoint 2 here <<<
{ //Manually push into if clause here and step forward (F10)
DateTime maxOwnerValidDate = DateTime.UtcNow; // Step forward here (F10). Exception thrown here.
// For some reason, if the next line is not present, the above statement succeeds without exception.
List<int> Ids = someStuff.Where(stuff => maxOwnerValidDate <= DateTime.UtcNow).ToList();
await Task.Delay(1000);
}
return true;
}
2
Answers
With normal execution, the code is hit and succeeds without error. However, manually manipulating the execution position causes the DateTime variable to fail to instantiate with an inexplicable exception.
When dragging the arrow, VS tries to warn you about this activity:
I will chalk this up to unintended consequences
Environment:
Neither
maxOwnerValidDate
(its struct) nor_dateData
(its primitive) can be null. So you misinterpreting something. Btw_dateData
field exists since NET Framework 2.0.Based on updated info you skipping closure object initialization (it captures state for lambdas or
async
functions).Here is decompiled code sharpLab
In your first example
maxOwnerValidDate
is not captured, so it’s not promoted to closure.