I got this great question from the mailbag:
“[W]hat is the relation between the “# line hidden” directive and the DebuggerNonUserCode attribute ? Are these the same ?”
They’re both markings that library authors can put in their source code to mark certain portions as “hidden” to the end-user while debugging. In both cases, the debugger must detect them and do additional work to respect them. Visual Studio respects both of these. MDbg only respects #line hidden. #line marks lines within a function as hidden whereas the DebuggerNonUserCode marks entire functions as hidden.
|What does it affect?||single set of continuous lines within a function||entire function or class|
|What does compiler do with it? (How could other languages besides C# use this)||Changes PDB mappings. Instructs the line to be mapped to 0xFeeFee, which serves as special value to debuggers to instruct it that that line is hidden.||Just a normal custom attribute, stored in the executable file.|
|More info on MSDN :||wiki link||wiki link|
|Example usage and more detail from my blog||here||here|
|Dependency on CLR||None. Existed since .NET 1.0.||Depends on Just-My-Code (JMC), which was added in .Net 2.0|
|What could debugger do with it?||This is purely a contract between the compiler and the debugger communicated via the PDBs.|
If debugger stops at a line that maps to ‘#line hidden’ it can elect to keep executing. It may elect to forbid breakpoints to be placed at hidden points. It stepping would normally stop at a hidden line, it may choose to continue stepping.
|This requires the debugger to use JMC support from the CLR debugging services.|
Debugger must use Just-My-Code stepping and mark functions as non-user code. Debugger marks frames with the DebugNonUserCode attribute as non-user code.
Note that since these are both enforced by the debugger, the debugger has to do extra work to make these features available to the end-user. But this also lets the debugger decide exactly what sort of policy it wants to expose. For example, the debugger can decide how to handle a breakpoint set in a function marked as DebuggerNonUserCode. (eg, Forbid it, warn the user, stop anyways, etc)