7

So, I have the following code:

static void Main(string[] args)
{
    var test1 = GeneratedHelperSync();
    var test2 = GeneratedHelperAsync().Result;
}

[System.Diagnostics.DebuggerNonUserCode]
static int GeneratedHelperSync()
{
    return RealCode();
}

[System.Diagnostics.DebuggerNonUserCode]
async static Task<int> GeneratedHelperAsync()
{
    // F11 steps in here!
    return await Task.FromResult(RealCode());
}

private static int RealCode() 
{ 
     return 1; 
}

And I F11 (step-into) through all the statements in Visual Studio 2013. I would expect that in both calls from Main() to step me into the "return 1" statement. However, in the second case, it steps me into the async function.

It seems that the compiler erases my DebuggerNonUserCode during the async code generation.
My question is, why is it doing that? Am I missing something?

As to why am I want this, I have some helper async functions that are automatically generated and I want to avoid stepping into them all the time.

Christoph Fink
  • 22,727
  • 9
  • 68
  • 113
dimio
  • 133
  • 1
  • 7

1 Answers1

4

This is a common "problem" with the async/await pattern. This happens to all attributes added to an async method (I had this happen with the ExcludeFromCodeCoverageAttribute and researched it a little).

What happens is, that the compiler splits the method up at the await and puts everything "after the await" into a new method, which is called when the await'ed task finishes. This new method does not get the attributes from the initial method - why I do not know.

The only way around this I know works for the ExcludeFromCodeCoverageAttribute is setting the attribute on a class level.

Christoph Fink
  • 22,727
  • 9
  • 68
  • 113
  • Yes, this same issue haunts ContextBoundObject related attributes with async/await: http://stackoverflow.com/q/22392997/495262 – Matt Smith May 05 '14 at 13:36
  • Does someone know, why the generated method does not inherit the attributes from the initial method? – Christoph Fink May 05 '14 at 13:40
  • It seems that there are others with the same problem, only a different Attribute! Setting the attribute to a class did not solve the problem though :( – dimio May 05 '14 at 13:42
  • Ok, did not know that. I edited the answer to refelct this (only?) works for the `ExcludeFromCodeCoverageAttribute`. I do not know anything else - maybe someone with better knowledge of this can help you. – Christoph Fink May 05 '14 at 13:48
  • 1
    Please do post these as issues on Microsoft Connect. – Stephen Cleary May 05 '14 at 14:06
  • @dimio, The reason putting the attribute at the class level doesn't work is that async/await creates a nested class (that won't get that attribute). I think it's not clear that it is a bug, since you may not want the async/await created code to always carry over the attribute (for example, consider you are placing an attribute that should only go on certain public entry points--you wouldn't want the attribute to carry-over to the generated async class/methods). – Matt Smith May 05 '14 at 14:24
  • @MattSmith: But why does the class-level attribute work for `ExcludeFromCodeCoverageAttribute`? – Christoph Fink May 05 '14 at 14:29
  • @MattSmith: IMO, System.Diagnostics.Debuggerxxx attributes that are sealed and are shipped with .Net should be propagated to the underlying generated classes and methods out of the box. Same goes for other similar attributes with clear use-cases. – dimio May 05 '14 at 14:43
  • @dimio, my point was that *in general*, it might not be desirable to propagate. The author of the attribute will most likely know whether it should propagate or not. – Matt Smith May 05 '14 at 14:46
  • yp, I got that. We should at least get a warning for the Debuggerxxx attributes – dimio May 05 '14 at 14:47
  • @chrfin, while the attribute will not be propagated to the nested class, the client of an attribute is free to apply any logic they choose in deciding what the attribute should apply to. I.e. they could look for the attribute on parent classes and deem it should apply. But I know nothing about the specific case you mentioned. – Matt Smith May 05 '14 at 14:48