Do debugging attributes such as [DebuggerDisplay] still get compiled into Release binaries? - c#

Having recently learned of the DebuggerDisplay attribute, I've found it quite useful. However, one thing that surprises me is that it doesn't have a [ConditionalAttribute("DEBUG")] attribute attached to it. Is there some way to force this or is it a bad idea to try? Or does it not matter for some other reason?

The [ConditionalAttribute("DEBUG")] is only used for optimising out method calls.
If you really want to remove these from your builds you can use #ifdef so that the code is only compiled in release mode.
One thing to bear in mind is that you can still debug binaries in release mode, as long as you have the pdb files it shouldn't matter. Release mode just clears up variables sooner and applies some compiler optimisations

As I often have to debug things in Release configuration builds that don't have the DEBUG directive, I would not want these hints to the debugger to be removed.
However, if you have some proprietary or confidential information in the way you display things when debugging that you don't want to make it into your release build, you may want to consider using the ConditionalAttribute or #if/#elif/#endif preprocessor directives to control what is emitted into your release builds.
For example, you could do:
#if DEBUG
[DebuggerDisplay...]
#endif
public class MyAwesomeClass
{
}
This would ensure the attribute is only emitted when the DEBUG directive is given.

I'll share a pattern that I've come to appreciate using partial.
public partial class MyClass{
//class details here
}
And then elsewhere:
#if DEBUG
[DebuggerDisplay("DebuggerValue")]
public partial class MyClass{
//anything needed for debugging purporses
}
#endif
This gives the ability to use DebuggerDisplay or other attributes without cluttering-up the base class.
I've been using a handful of files, all wrapped in #if DEBUG to hold these Debug-Partials. It helps keep the core classes cleaner and I don't have to remember to start/end compiler directives for each attribute.

I would think it would be a bad idea, because a lot of times the thing you're attaching the attribute to has some other use besides just showing it in the debugger, IMO.

Related

How can I avoid `#if DEBUG` directives for members in C#?

I use a log property in my class that is intended only for debugging purposes.
Note: I do not use any existing logger packet, as I manage a large lists of objects each of them having its own (!) log.
As it is not used in release mode, it is enclosed by a preprocessor directive:
#if DEBUG
public List<LogItem> DebugLog { get; }
#endif
Unfortunately, I need to initialize and copy this property a few times, leading to messy code like this:
public MyClass(object parameterA, object parameterB, ...,
#if DEBUG
, List<LogItem> debugLog
#endif
) {
throw new NotImplementedException();
}
Whilst for actual logging, I wrote a [Conditional("DEBUG")] method, I am not aware of any possibility avoiding this ugly and idiom-violating directives for noting arguments and parameters. The ConditionalAttribute appears to be only applicable on properties and attributes.
I am wondering whether there is any design pattern for this problem enabling a better readability. I am looking forward to your ideas!
Have a look at log4net, which is probably the most popular open-source logger for .NET. One of the many benefits you'll see is that you can configure the logger once, in your config file, and have different configurations for debug and release. That way, switching to release is done automatically when you publish the web site or app, you don't have conditional directives in your code, and you don't need to change the code to account for different situations.

Is there a way to make Code Analysis ignore "InternalsVisibleTo"?

We have a lot of assemblies that contain internal classes which we are unit-testing by using InternalsVisibleTo to make the internal classes visible to the Unit Test assembly.
This works fine, but the problem is that as soon as you use InternalsVisibleTo, it prevents the Code Analysis CA1812 warning (Avoid uninstantiated internal classes).
It also prevents CA1811: "Avoid uncalled private code".
I've done some investigation, and I've found quite a lot of unused internal classes that we weren't being warned about because of this.
My solution for the moment is to hand-edit the "AssemblyInfo.cs" file in each assembly to temporarily comment-out the InternalsVisibleTo so that I can compile just that project and discover unused internal classes.
This is a huge hassle, and of course if something like that doesn't get done automatically, it frequently doesn't get done at all.
A solution would be to be able to tell Code Analysis to ignore the InternalsVisibleTo attribute.
Does anyone know if such a possibility exists?
Try this:
#ifdef CODE_ANALYSIS
#else
[InternalsVisibleTo(...)]
#endif

#define directive purpose

What is the purpose and good usage of #define directive in C#?
There are already few questions on this topic but no answer I need. They only give examples how it works. But I need deeper explanation: why does it exist and what are good ways of using it (if any).
Basically I know how to use it, but for me the usage looks odd. Let's look at example:
#define DEV
#if DEV
Console.WriteLine("Development trace log message");
#endif
For me this is completely different from using #if conditional build with project-defined conditional compilation symbols. If we use project-defined symbol, it is attached to project build configuration and we can manage code needed to build (and excluded from build) with build configuration used. So code
#if DEBUG
Console.WriteLine("Debug log message");
#endif
is fine for me. But as I said it is completely different from using #define directive because it is managable.
Am I correct that 1st example can be managed only manually commenting/uncommenting #define line on every build? If yes, it is not managable, hard-to-maintain and I think this usage of #define is extreemely bad practice and sholdn't exists in the language at all.
I can imagine usage of #define/#undef inside #if statement. Something like
#if DEBUG
#if CLIENT1
#define TEST_CLIENT1
#endif
#endif
#if TEST_CLIENT1
connectionString = "Some specific test connection" //I know this is bad practice even in conditional. Only for example purpose.
#elif
//Read connection from config
#endif
#if UNITTESTS
#undef TEST_CLIENT1
#endif
#if TEST_CLIENT1
Console.WriteLine("Some message");
#endif
Sorry for so complicated example, but that is at least something I can find useful. Though I wouldn't write such code in any way =).
Is there any good usage of #define?
PS: I never used #define myself for 5 years and had no will to do it, but I got a support project which has many strange defines which even named in an odd way. Those defines usually placed at the top of the file, like in my 1st example here. And I have no idea how to maintain this code.
I can't see any valid reason for it other than without it, the #IF statement wouldn't exist.
When you define project level precondition variables using the /define directive on the compiler all it really does is add a #DEFINE to the code.
I would argue that this makes it manageable but not in setting it manually in the code, using the /define statement.
The other usefulness is readability and scope. Project defined statements apply to the project, #DEFINE level statements only apply to one file. This helps keep things organised, readable and stops variable issues.
'#define' is there because people expect it to be there. :) For your purposes (e.g. a large project) it may make more sense to keep preprocessor symbols in your project. For quick debugging or other purposes #define may be the best choice. Additionally, #define allows fine-grained (file level) control of symbols.
Imagine you have a large codebase and a single module that is giving you trouble. You might wish to '#define TRACE' or '#define DEBUG' only in the single file where you want to enable tracing/debugging for performance reasons.

Does Debug.Assert generate IL in release mode?

When Debug.Assert() method calls exist in source code and I compile in release mode, does the compiler generate the IL for the Debug.Assert() even though it's not called?
One of our developers added an Assert recently that displays information about our internal security. Could someone look at the release mode IL and figure out the text for the assert?
No, the members of the Debug class (with the ConditionalAttribute attribute) do not emit IL. There is no explicit mention on MSDN, however the following two quotes imply the behaviour quite well, so to augment Roy's answer:
If you use methods in the Debug class to print debugging information
and check your logic with assertions, you can make your code more
robust without affecting the performance and code size of your
shipping product.
So, no size difference implies no output from these whatsoever, and
The ConditionalAttribute attribute is applied to the methods of Debug.
Compilers that support ConditionalAttribute ignore calls to these
methods unless "DEBUG" is defined as a conditional compilation symbol.
Refer to a compiler's documentation to determine whether
ConditionalAttribute is supported and the syntax for defining a
conditional compilation symbol.
Which means that, at the compiler level, these calls won't even be considered (when DEBUG is not defined.)
It does not by default, unless you define the DEBUG symbol (and by default, for Release that is turned off).
To verify, open your Project Properties and select the Build pane in Visual Studio. It will show the checkbox "Define DEBUG constant". If it is turned on for Release, then asserts will fire; otherwise, they won't.

Debug vs Trace in C#

As I understand statements like Debug.WriteLine() will not stay in the code in the Release build. On the other hand Trace.WriteLine() will stay in the code in the Release build.
What is controling this behaviour? Does the C# compiler ignores everything from the System.Diagnostics.Debug class when the DEBUG is defined?
I am just trying to understand the internals of C# and just curious.
These methods use the ConditionalAttribute to designate when they should be included.
When DEBUG is specified as a #define, via the command line or the system environment (set DEBUG = 1 in the shell), a method marked with [Conditional("DEBUG")] will be included by the compiler. When DEBUG is not included, those methods and any calls to them will be omitted. You can use this mechanism yourself to include methods under certain circumstances and it is also used to control the Trace calls like Trace.WriteLine (this uses the TRACE define).
This is due to ConditionalAttribute; the compiler ignores calls to methods marked as conditional unless that symbol is defined.
You can have your own:
[Conditional("BLUE")]
void Bar() {...}
which will only be called when BLUE is defined.
Note that there are some restrictions, to make "definite assignment" work:
no return value
no out parameters
(the same restrictions apply to partial methods for similar reasons)

Categories

Resources