Here's some simple code:
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();
}
}
The question is, why the following steps make it crash with NullReferenceException :
1) Breakpoint to the if
2) Set the next execution point:
3) Try to continue with F10:
If I comment out the last line of the code, it won't crash.
Update: Here's the stack trace:
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:
This is a side-effect of moving the execution point inside a context that declares a captured variable scope. It would be reasonable to report it as an IDE bug, but it would not be trivial to fix. Basically, date
is not a variable - it is a field on a capture-context, because of the lambda. The compiler essentially does:
if (!filteredColl.Any())
{
var ctx = new SomeCaptureContext(); // <== invented by the compiler
ctx.date = new DateTime();
filteredColl = coll.Where(ctx.SomePredicate).Select(x => x).ToList();
}
where SomePredicate
is:
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;
}
}
The problem here is that when you drag the execution position to:
DateTime? date = new DateTime();
You are actually (in IL terms) dragging it to the line:
ctx.date = new DateTime();
The capture-context line immediately before that, ie
var ctx = new SomeCaptureContext();
never got executed, so ctx
is null
. Hence the NullReferenceException
.
It would be reasonable to log this as a bug, but it is a subtle one - and you wouldn't necessarily always want dragging the execution context to initialize the capture-contexts - it would have to be "if they are null
".
Hmm... Really it looks weird. Do you have mscorlib in references and System in usings? Maybe you have some another class named DateTime and it overrides System.DateTime.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.