1

I'm aware that you can use #if DEBUG and the likes in C#, but is it possible to create a method, or class, that is ignored completely, including all usages that are not wrapped inside an #if DEBUG block?

Something like:

[DebugOnlyAttribute]
public void PushDebugInfo()
{
    // do something
    Console.WriteLine("world");
}

and then:

void Main()
{
    Console.WriteLine("hello ");
    Xxx.PushDebugInfo();
}

which, if DEBUG is defined will print "hello world", otherwise just "hello ". But more importantly, the MSIL should not contain the method-call at all in release builds.

I believe the behavior I'm after is something similar to Debug.WriteLine, whose call is completely removed and has no impact on performance or stack depth in release builds.

And, if possible in C#, would any .NET language using this method behave the same (i.e., compile-time vs run-time optimization).

Also tagged , because essentially I will need this method there.

Abel
  • 56,041
  • 24
  • 146
  • 247

3 Answers3

7

It seems like you're looking for ConditionalAttribute.

For example, this is a portion of Debug class source code:

static partial class Debug
{
    private static readonly object s_ForLock = new Object();

    [System.Diagnostics.Conditional("DEBUG")]
    public static void Assert(bool condition)
    {
        Assert(condition, string.Empty, string.Empty);
    }

    [System.Diagnostics.Conditional("DEBUG")]
    public static void Assert(bool condition, string message)
    {
        Assert(condition, message, string.Empty);
    }
 ................................
Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
  • Are these methods compiled in any release and removed by the JIT or are they, as MSDN says, removed by the compiler (which requires two builds for others to use, dependent on their debug settings)? – Abel Sep 17 '15 at 09:49
  • @Abel It's a compilation detail. JIT has nothing to do with this. BTW, build configurations are very easy to configure, aren't they? – Matías Fidemraizer Sep 17 '15 at 09:55
  • Yes, they are. Anyway, it gives me enough ammo to go on. It has this "aha-erlebnis" feeling, I think I have used or seen this years ago, but forgot about it ;). – Abel Sep 17 '15 at 09:57
  • 1
    @Abel .NET ecosystem is big enough to forgot details in the long run :D – Matías Fidemraizer Sep 17 '15 at 09:57
1

You can decorate your method with [Conditional("DEBUG")] so that it is only executed in debug mode and will not be executed in Release mode.

You can read more about the Conditional attribute on MSDN which says:

The Conditional attribute is often used with the DEBUG identifier to enable trace and logging features for debug builds but not in release builds

Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160
  • Seems like the thing I was looking for. What happens then if I have `var x = Xxx.SomeDebugOnlyMethod()`? A compile time error? Do you know if something similar exists that does not require two builds, but can be optimized away by the JIT? – Abel Sep 17 '15 at 09:44
  • @Abel what you mean by ``SomeDebugOnlyMethod()`` , did'nt got your point – Ehsan Sajjad Sep 17 '15 at 09:46
  • it will not execute the code where `x` is referenced next in release mode – Ehsan Sajjad Sep 17 '15 at 09:49
  • Yes. No, sorry. I meant: I assign the value to a variable. If the rh-side is not compiled, it should become a compile error, right? – Abel Sep 17 '15 at 09:52
  • 1
    Just found it: _"A conditional method must be a method in a class or struct declaration and must have a return type of void."_, from MSDN. – Abel Sep 17 '15 at 09:54
1

I've seen the following method used in some places, although it might not be the best way.

public static class Debug
{
    public static bool IsInDebugMode { get; set; }

    public static void Print(string message)
    {
        if (IsInDebugMode) Console.Write(message);
    }
}

You can then set the IsInDebugMode boolean somewhere in your main method and do Debug.Print("yolo") calls all over.

EDIT: This can of course be expanded on with additional wrappers for formatted output, with automatic newline and so on.

sara
  • 3,521
  • 14
  • 34
  • No, this is indeed not what I was looking for, as it will still execute the method. I am trying to prevent this. In tight loops, this would have a detrimental effect on performance. – Abel Sep 17 '15 at 09:45
  • I've only used this in Java for small home projects where it's been a quick way to get debug printing up and running but yeah, if performance is critical (meaning that it's proven/demonstrably necessary to optimize) this might not be optimal (although a bool check is really cheap so you might get away with it anyway). I've never used the `ConditionalAttribute` but that looks promising so it might suit you better though. – sara Sep 17 '15 at 09:51
  • @freedomn-m, in most cases it would suffice, it is how we use logging and log settings. But in some scenarios, I need to gather information in tight loops, in which case it would be better not to have the method-call at all. And there's the scenario, of course, with security-sensitive information that you only want to have present in debug builds. – Abel Sep 17 '15 at 09:51
  • Personally, I prefer this method as it means you can turn on debug in a production environment without needing to recompile. However, in some cases (such as this question) the overhead it too high. – freedomn-m Sep 17 '15 at 09:53