12

The DebuggerStepThrough attribute allows you to skip breaking into certain methods/classes/properties.

In DebuggerStepThrough being ignored it is clarified that the c# compiler does not inherit this attribute into the compiler generated IEnumerable<T> implementation.

A trivial example of such a failure is:

static void Main(string[] args)
{
    var a = SkipMe().ToList();
}

[System.Diagnostics.DebuggerStepThrough]
static IEnumerable<int> SkipMe()
{
    // comment out line below and the throw will be stepped over.
    yield return 1;
    throw new Exception();
}

Is there a way to get the C# compiler to add the DebuggerStepThrough attribute to the auto generated type?

Is there a way to get visual studio to skip debugging into any types with the [CompilerGenerated] attribute?

--

Addendum: some illustrative screenshots

Result after pressing F5

screen 1

screen 2

Visual Studio Version:

snip 3

Our missing attribute:

the missing attribute

Community
  • 1
  • 1
Sam Saffron
  • 128,308
  • 78
  • 326
  • 506
  • for those wondering why, when using Dapper we include it as a blob of source, I would like to avoid stepping into any Dapper code during regular use and do not want to add a dll to the project just for that. – Sam Saffron Jan 06 '12 at 00:18
  • I can't make sense of this question. The compiler already applies the [DebuggerHidden] attribute to the iterator class methods. The example in the snippet doesn't make sense, the debugger always stops on an uncaught exception. The comment in the SkipMe() method doesn't make sense, it does *not* step over the throw statement. At least not in VS2008, can't tell what version you're talking about. – Hans Passant Jan 06 '12 at 09:32
  • 1
    @hans vs 2010 .net 4, the iterator only has compiler generated, I checked in reflector – Sam Saffron Jan 06 '12 at 10:15
  • No difference in VS2010 SP1. This works like it should. The method attributes matter, not the iterator class attributes. Note that SP1 has important debugger fixes, relevant to your comment in SkipMe perhaps. Key point is that the debugger is going to stop on the throw regardless of attributes. That's a Good Thing. – Hans Passant Jan 06 '12 at 10:27
  • @HansPassant edited and added some screenshots – Sam Saffron Jan 06 '12 at 10:56
  • The only way I can repro the 2nd screenshot is by debugging the Release build. If this also happens in the Debug build for you then make the version number screenshot a bit bigger to show what hotfixes you have installed. – Hans Passant Jan 06 '12 at 11:10
  • I am in debug @HansPassant and so are all the screen shots targeting the full framework with kb2522890, kb2529927, kb2547352, kb2548139 kb2549864, kb256505 ... running in x64 and x32 – Sam Saffron Jan 06 '12 at 11:15
  • I also got kb2565057 (security update) and kb2581319 (can't find it). And yes, MoveNext doesn't have [DebuggerHidden] but it is a private method. It could be argued that it works like it should in your case, the throw statement actually *is* hidden. I however like the way it works on mine much more :). No idea why I can't repro, I gave it my best shot. – Hans Passant Jan 06 '12 at 11:35
  • @HansPassant I can explain what is happening on your machine, 1. you do not have "just my code" checked. 2. In release that tiny method is being inlined. – Sam Saffron Jan 06 '12 at 21:45

1 Answers1

3

I don't think there is a way to achieve the effect you're looking for.

  • There is no way to make the C# compiler copy this attribute into the generate state machine method.
  • You can't get around this by adding DebuggerStepThrough to the class containing the iterator method. The debugger only looks at the immediate parent type not the types containing a nested type.

The only real way I can think of to achieve this is to put all of the code you don't want to debug into in a separate DLL. Then don't load the PDB for that particular DLL.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 1
    well there is one more way ... you could PostSharp or Mono.Cecil to inject the attribute in a secondary compile :) but yeah ... this is pretty much what I thought. – Sam Saffron Jan 06 '12 at 00:44
  • @SamSaffron yes. Definitely possible via some sort of post IL rewriting process. – JaredPar Jan 06 '12 at 00:45
  • @SamSaffron there's another way: implement your own enumerator class, apply the attribute there, and return an instance of that from the SkipMe method. – phoog Jan 06 '12 at 01:13
  • @Jared - please take a look at the comments under the question. Something else is going on. – Hans Passant Jan 06 '12 at 11:44
  • @HansPassant when the question was first posed it didn't have the screen shots and only mentioned `DebuggerStepThrough`. My answer was geared towards that version of the question. Breaking on exceptions and `DebuggerStepThrough` are orthogonal concepts IIRC. The rules for where it will / won't break aren't something I'm familiar enough to say with certainty. – JaredPar Jan 06 '12 at 16:00
  • @HansPassant if you have "just my code" enabled in debugging options, the debugger pretty much "pretends" the methods decorated with stepthrough do not exist, including flowing the "break on exception" up in the stack to non decorated methods. The documentation on msdn is pretty sloppy in explaining how it works. – Sam Saffron Jan 06 '12 at 21:32