Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E&C: Using a lambda-captured variable in an async method throws NRE at runtime & debugger #15542

Open
SLaks opened this issue Nov 27, 2016 · 1 comment

Comments

@SLaks
Copy link
Contributor

SLaks commented Nov 27, 2016

Version Used: 2017 RC

static async Task<IEnumerable<int>> M(int x) {
	return new int[1].Select(i => x);
}
static void Main(string[] args) {
	for (int i = 0; i < 4; i++) {
		try {
			M(1).Wait();
		} catch (Exception ex) {
			Console.WriteLine(ex);
		}
	}
}

Set a breakpoint on the return statement, then paste x = x;.

Continuing execution will throw the following exception on the first call only:

System.AggregateException: One or more errors occurred. ---> System.ArgumentException: Delegate to an instance method cannot have null 'this'.
   at System.MulticastDelegate.CtorClosed(Object target, IntPtr methodPtr)
   at ConsoleApplication1.Program.<M>d__0.MoveNext()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait()
   at ConsoleApplication1.Program.Main(String[] args)
---> (Inner Exception #0) System.ArgumentException: Delegate to an instance method cannot have null 'this'.
   at System.MulticastDelegate.CtorClosed(Object target, IntPtr methodPtr)
   at ConsoleApplication1.Program.<M>d__0.MoveNext()<---

In addition, the x parameter will throw an NRE in the Locals window on all subsequent calls until the debugger is restarted.

@SLaks
Copy link
Contributor Author

SLaks commented Nov 27, 2016

If you use x directly before the breakpoint, you'll get a simple NRE from MoveNext at runtime instead.

Specifically,

static async Task<IEnumerable<int>> M(int x) {
	x = x;

	return new int[1].Select(i => x);
}

Set a breakpoint on the first line and duplicate it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants