dlchambers
dlchambers

Reputation: 3752

How to make conditional attributes in C#?

I want to hide some member vars in my C# class.
I can do this via the DebuggerBrowsable attribute:

using System.Diagnostics;

[DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
int myvar;

However, I only want this attribute to be applied for Release builds - I want to hide the var from my assembly's Release-build consumers but I want the var visible in Debug builds for inspection during dev, etc.

I could, but would prefer not to, wrap each attribute in an #if block:

#if !DEBUG
        [DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
#endif

That would do the trick, but creates some pretty messy-looking code.

If I were in C++/CLI - and had macros - I could do this:

#ifdef _DEBUG
#define HIDDEN_MEMBER
#else
#define HIDDEN_MEMBER   [System::Diagnostics::DebuggerBrowsableAttribute(System::Diagnostics::DebuggerBrowsableState::Never)]
#endif

and then

HIDDEN_MEMBER
int myvar;

But no macros in C# :(

Any bright ideas as to how to achieve the macro-like syntax in C#?

Upvotes: 3

Views: 2579

Answers (4)

sloth
sloth

Reputation: 101052

Just another suggestion, using a type alias:

#if DEBUG
using HiddenMember = global::DummyAttribute.HiddenMember;
#else
using HiddenMember = global::System.Diagnostics.DebuggerBrowsableAttribute;
#endif

namespace DummyAttribute
{
    class HiddenMember : Attribute
    { public HiddenMember(DebuggerBrowsableState dummy) { } }
}

Usage:

public class YourClass
{
    [HiddenMember(DebuggerBrowsableState.Never)]
    int YourMember = 0;
}

Feel free to hide the DebuggerBrowsableState.Never argument behind a constant.

Upvotes: 1

dlchambers
dlchambers

Reputation: 3752

Here's something that I came up with, which I like:

In the base class:
#if DEBUG
   [DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
   internal const System.Diagnostics.DebuggerBrowsableState BROWSABLE_ATTRIB = System.Diagnostics.DebuggerBrowsableState.Collapsed;
#else
   [DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
   internal const System.Diagnostics.DebuggerBrowsableState BROWSABLE_ATTRIB = System.Diagnostics.DebuggerBrowsableState.Never;
#endif

which works for me because all my objects have a common base, however deep it may be.
Note that I'm hiding BROWSABLE_ATTRIB... I don't want that const publicly visible.

Then in any derived class:

[DebuggerBrowsable(BROWSABLE_ATTRIB)]
int myvar;

I prefer this to @Olivier's answer, though I thank him kindly for posting it.
While a ternary in each attribute is better then the #if #else #endif mess, it's still more verbose than I'd prefer.

I was also unaware of ConditionalAttribute; thanks @Tony for that. While it may not solve this particular situation I can see how it could be very useful in others and I'm grateful to add it to my bag of tricks.

Upvotes: 0

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112342

Try

const bool debugging = true;

And then

[DebuggerBrowsableAttribute(debugging ? DebuggerBrowsableState.Collapsed
                                      : DebuggerBrowsableState.Never)]

Upvotes: 2

Tony Basile
Tony Basile

Reputation: 419

See the ConditionalAttribute class, you can apply the [Conditional] attribute to the [DebuggerBrowsable] attribute.

Upvotes: 2

Related Questions