How can I avoid `#if DEBUG` directives for members in C#? - 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.

Related

How to emit compiler errors for unfinished features in Release Mode for .NET code?

Being inspired by this article I asked myself how can I emit compiler errors or , at least stop the build, if a feature is not implemented.
The only quick solution I came up with, is by creating a custom attribute:
public class NoReleaseAttribute : System.Attribute
{
public NoReleaseAttribute()
{
#if RELEASE
.
#endif
}
}
The idea is to have a syntactic error somewhere, but only for Release. I used an attribute because the IDE will help me find quickly the references to the attribute, and thus all places that I marked as needed to be completed or fixed before going in production.
I don't like this solution because I want one to emit a compiler error in each place that needs attention, not a single global error elsewhere.
Perhaps there is a more fitted solution.
You may use #error directive in your code, it will cause an error at compile-time.
Example usage:
static void Main(string[] args)
{
DoSomeStuff();
}
#error Needs to be implemented
static void DoSomeStuff(){
//This needs some work
}
There are no more fitted solution. You can use for your goal:
a) ObsoleteAttribute (may not fit your goal)
b) throw NotImplementedException in every place that you need to:
#if RELEASE
throw new NotImplementedException();
#endif
c) Wrap throwing NotImplementedException with attribute as you described us.
Basically it is unnecessary to add code that will not be used anywhere - Visual Studio even marking this code with 0 usages and it will not be included in CIL. So you have to question yourself - do i really need useless code exist in our project? It is better to track unreleased features in tracking systems like YouTrack or something, than to search them in your code.
I would suggest using a build step that checks the code for TODO-comments and generates warnings for them. A quick google suggest the Warn About TODOs extension might do just that, but it is not something I have used. You should also configure your build to fail on most warnings. A possible risk here is that people will just avoid using todo-comments, since they will fail the build.
But needing such a check suggest you do not have sufficient testing of your code. I find it a good practice to at least do some level of testing before committing any code, and just about any testing should reveal if entire components are not implemented. Reviewing your own code before committing is another practice that could be useful.
Automated unit testing can be a great way to deal with things like this. If you write unit tests for all your components the tests should find things like this, especially if you throw NotImplementedException in placeholders. This might require you to write your tests before the components, but there are certainly arguments for such a development approach.
The next line of defense should be code review. Even a quick review should find methods that are not implemented.
The final line of defense should be independent testing. If someone else tests the new features against the specification, any significant missing functionality should be found.

Throwing an exception vs Contract.Requires<T>?

I'm wondering whether should I throw exceptions or call Contract.Requires<TException>
For example:
public static void Function(String str)
{
if (str == null) throw new ArgumentNullException("str", "Input string cannot be null.");
// ...
}
vs
public static void Function(String str)
{
Contract.Requires<ArgumentNullException>(str != null, "Input string cannot be null.");
// ...
}
Since Contract.Requires<TException> doesn't require the CONTRACTS_FULL symbol I can keep it in my release builds as well.
This is my consideration:
Con: You can't call an overloaded version of the custom exception type constructor. There is simply no way to pass additional parameters to the constructor.
Pro: Static tools support (e.g. inform the caller of contract violation).
Which one should I use, and for what kind of situation?
The basic trade-off between if-then-throw and Requires<TException> as documented in the CodeContract user guide is how you build with your release bits.
Case 1: You only use if-then-throw, no Requires<TException>. In this case you can build your release bits without running the contract tools on your dll/exe. The advantage is that you have faster builds and no risk that the tool introduces bugs. A second advantage is that team members can opt out of using the CodeContract tools. Disadvantages are that you get no contract inheritance of requires, and your contracts are not necessarily visible to the tools (unless you use EndContract). You specify this case by using assembly mode: Custom Parameter Validation
Case2: You decide to run the CodeContract tools on your release bits always. This lets you use Requires<TException> and you get inheritance of contracts, including instrumentation of interfaces etc. Your contracts are clean and tool recognizable. The disadvantage is that everyone building your code must have the CodeContracts tools installed. You specify this case by using assembly mode: Standard in the Contract property pane.
Hope this clear things up.
I'm not sure that there are any earth-shattering differences between the two approaches, but here are two reasons why I prefer contracts...
1) The code is much neater, as you are writing a statement at the top of the method that shows the assumptions upon which the method is based. You don't clog up the code with the implementation of what happens if the assumption is violated.
2) You get the benefit of Visual Studio picking up on the code contracts when you are writing code, and giving you hints as to what the method you are about to call expects. This helps you ensure that you are sending the method valid parameters, without having to jump to the method definition to check the code there.
Once the code is compiled and running, I don't think there are any significant differences.
Hope this helps.

ILogger _logger.Debug("Something") - Any way for the compiler to remove it?

I got a pretty common scenario, namely a self implemented ILogger interface. It contains several methods like _logger.Debug("Some stuff") and so on. The implementation is provided by a LoggingService, and used in classes the normal way.
Now I have a question regarding performance, I am writing for Windows Phone 7, and because of the limited power of these devices, little things may matter.
I do not want to:
Include a precompiler directive on each line, like #IF DEBUG
Use a condition like log4net e.g. _logger.DebugEnabled
The way I see it, in the release version, I just return NullLoggers, which contain an empty implementation of the interface, doing nothing.
The question is: Does the compiler recognize such things (may be hard, he can't know on compile time which logger I assign). Is there any way to give .NET a hint for that?
The reason for my question, I know entering an empty function will not cause a big delay, no problem there. But there are a lot of strings in the source code of my application, and if they are never used, they do not really need to be part of my application...
Or am I overthinking a tiny problem (perhaps the "string - code" ratio just looks awful in my code editor, and its no big deal anyway)..
Thanks for tips,
Chris
Use the Conditional attribute:
[Conditional("DEBUG")]
public void Debug(string message) { /* ... */ }
The compiler will remove all calls to this method for any build configurations that don't match the string in the conditional attribute. Note that this attribute is applied to the method not the call site. Also note that it is the call site instruction that is removed, not the method itself.
It is probably a very small concern to have logging code in your application that does not "run". The overhead of the "null" logger or conditionals is likely to be very small in the scheme of things. The strings will incur memory overhead which could be worrying for a constrained device, but as it is WP7 the minimum specs are not that constrained in reality.
I understand that logging code looks fugly though. :)
If you really want to strip that logging code out...
In .Net you can use the ConditionalAttribute to mark methods for conditional compilation. You could leverage this feature to ensure that all logging calls are removed from compilation for specified build configurations. As long as methods that you have decorated with the conditional attributes follows a few rules, the compiler will literally strip the call chain out.
However, if you wanted to use this approach then you would have to forgo your interface design as the conditional attribute cannot be applied to interface members, and you cannot implement interfaces with conditional members.

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

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.

Is there a way to assign conditional methods or add preprosessor directives at run-time in C#?

The aim is to be able to switch debugging calls on at run-time from database on a production build ...
No; the point of conditional methods and preprocessor directives is that they cause the compiler to omit code from the final executable. The runtime equivalent of these is an if statement.
However, aspect-orientated programming is roughly equivalent to what you're asking, in that it allows you to inject code into a running program that wouldn't otherwise be there.
Edit: as Joe mentioned, the way to do this is to program against a logging framework like log4net that allows fine-grained control over what gets logged.
Not at the pre-processor level. After all, you're running the result of that process. Of course, you could change your pre-processor checks to be normal code checks, which can obviously be switched as required.
No, but most logging subsystems provide this ability. E.g. with log4net you can change the logging level dynamically, or if using System.Diagnostics.Trace you can change the TraceSwitch level dynamically.
You obviously can't affect the binary code as such (as with the #if statement).
What I usually do is to make sure that my code contains a lot of logging, that is activated by trace switches. That way you can have a system run in production with little or no logging, and when you want to research some problem you can switch logging on by altering the config file.

Categories

Resources