views:

66

answers:

2

I need to implement a HtmlHelper extension in my MVC project simply just to output some string but ONLY in the DEBUG mode, not in RELEASE. My first attempt would be:

[Conditional("DEBUG")]
public static string TestStringForDebugOnly(this HtmlHelper helper, string testString)
{
    return testString;
}

But obviously that would give a compile error:

"The Conditional attribute is not valid because its return type is not void."

So my understanding is once you set the [Conditional] attribute, it doesn't allow anything to be returned? Why?

Is there another way to implement this kind of function? Any help would be much appreciated.

Thanks!

+5  A: 

You can use a preprocessor directive:

public static string TestStringForDebugOnly(this HtmlHelper helper, string testString)
{
#if DEBUG
    return "debug";
#else
    return "other";
#endif
}

As far as your original question as to why, a peek at section 17.4.2 of the C# specification indicates:

[A] conditional method must have a return type of void

I can only speculate as to why the designers of the language decided this, but I would venture to guess it's because the C# compiler does not compile the method call into IL if the condition is false, so in effect it's as if you never called the method (which would cause some obvious problems at run-time if a return value was expected!)

John Rasch
perfect! thank you sir.
BeCool
+1 For how you read the mind of the language designers. I never understood how people want to do that. Maybe if I get older and wiser...
Malcolm Frexner
@Malcolm: The mind of the language designers wasn't the only thing he was reading...
Neil T.
@Neil - I am confused by your last comment
John Rasch
+1  A: 

I don't know if the original designers had this line of thinking in mind originally, but this is how it makes sense to me.

Because you can only declare the method as type void AND it cannot be overridden AND it cannot be referenced as part of an interface, the compiler can simply ignore the method because it will have no dependencies if the specified mode doesn't match. If another method calls it in a non-matching mode, the compiler can simply treat it an invalid method call as if the attribute wasn't there.

John's example will work, but I would do something like this:

#if DEBUG
public static string TestStringForDebugOnly(...)
{
    ...
}
#endif

// Arguments are only for illustration.
public string CallingMethod(int id, string temp)
{

    #if DEBUG
    string result = TestStringForDebugOnly(id, temp);
    #else
    string result = TestString(id, temp);
    #endif

    return result;
}

I would expend the additional effort to wrap up all the DEBUG-related code (including the individual method calls) in preprocessor directives for two reasons. First, it provides its own built-in documentation; you know exactly what is supposed to run when, where and why. Second, if the code needs to be modified or removed, the amount of searching that needs to be done is greatly reduced, along with the need to repeatedly compile and re-compile to see what breaks.

Neil T.