By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,710 Members | 1,626 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,710 IT Pros & Developers. It's quick & easy.

Debug.Assert puzzle!

P: n/a
I have a question regarding asserting ... here's some code:

string GetAssertMessage()
{
... prepare a message string and return it...
}

void SomeMethod()
{
...
Debug.Assert(condition, GetAssertMessage());
...
}

Even if condition is true, GetAssertMessage() will still be evaluated
as it's a parameter to a function. How can I best avoid the cost of
GetAssertMessage() if the condition is false and not in DEBUG mode? I
also read that I shouldn't really put function calls into an Assert
statement (MSDN "Assertions in Managed Code").

Idea 1:

#ifdef DEBUG

string GetAssertMessage()
{
... prepare a message string ...
}

#endif

void SomeMethod()
{
...
#ifdef DEBUG
if (!condition)
{
string message = GetAssertMessage();

// could use Debug.Fail without condition
Debug.Assert(condition, GetAssertMessage());
}
#endif
}

Surely there must be something a little more elegant than this? It
just makes the code ugly.

Any ideas or have I done the best I can here?

Thanks!

Emma Middlebrook
em*************@fastmail.fm
Nov 15 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
emma middlebrook <em**************@fastmail.fm> wrote:
I have a question regarding asserting ... here's some code:

string GetAssertMessage()
{
... prepare a message string and return it...
}

void SomeMethod()
{
...
Debug.Assert(condition, GetAssertMessage());
...
}

Even if condition is true, GetAssertMessage() will still be evaluated
as it's a parameter to a function. How can I best avoid the cost of
GetAssertMessage() if the condition is false and not in DEBUG mode? I
also read that I shouldn't really put function calls into an Assert
statement (MSDN "Assertions in Managed Code").


If you don't have DEBUG defined, it won't get evaluated at all. Here's
some sample code:

using System;
using System.Diagnostics;

public class Test
{
static void Main(string[] args)
{
Debug.Assert (true, GetMessage());
}

static string GetMessage()
{
Console.WriteLine ("GetMessage called");
return "message";
}
}

When DEBUG is defined, "GetMessage called" will be produced on the
console. When it's not, the message won't appear.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #2

P: n/a
Jon

Thanks for your reply ...
If you don't have DEBUG defined, it won't get evaluated at all.


Yes, I got that far :-) I was really more interested in whether anyone
had a better way than the below usage of the DEBUG symbol i.e. using
the preprocessor *as well as* testing for the condition *as well as*
using Debug.Fail or Debug.Assert in that block too! Something just
doesn't seem right about this code - looks a bit clumsy. Or am I
worrying too much?

#ifdef DEBUG
string GetAssertMessage()
{
... prepare a message string ...
}
#endif

void SomeMethod()
{
...
#ifdef DEBUG
if (!condition)
{
string message = GetAssertMessage();

// could use Debug.Fail without condition
Debug.Assert(condition, GetAssertMessage());
}
#endif
}

Thanks!

Emma Middlebrook
em**************@fastmail.fm
Nov 15 '05 #3

P: n/a
emma middlebrook <em**************@fastmail.fm> wrote:
Thanks for your reply ...
If you don't have DEBUG defined, it won't get evaluated at all.


Yes, I got that far :-) I was really more interested in whether anyone
had a better way than the below usage of the DEBUG symbol i.e. using
the preprocessor *as well as* testing for the condition *as well as*
using Debug.Fail or Debug.Assert in that block too! Something just
doesn't seem right about this code - looks a bit clumsy. Or am I
worrying too much?


I think you're worrying too much - what's wrong with just:

Debug.Assert (condition, GetAssertMessage());

?

GetAssertMessage doesn't get invoked when DEBUG isn't defined, so
what's the disadvantage? You end up with a *slightly* larger assembly
(as the method is still present) but it'll never even be JITted.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #4

P: n/a
emma middlebrook wrote:
Jon

Thanks for your reply ...

If you don't have DEBUG defined, it won't get evaluated at all.

Yes, I got that far :-) I was really more interested in whether anyone
had a better way than the below usage of the DEBUG symbol i.e. using
the preprocessor *as well as* testing for the condition *as well as*
using Debug.Fail or Debug.Assert in that block too! Something just
doesn't seem right about this code - looks a bit clumsy. Or am I
worrying too much?

#ifdef DEBUG
string GetAssertMessage()
{
... prepare a message string ...
}
#endif

void SomeMethod()
{
...
#ifdef DEBUG
if (!condition)
{
string message = GetAssertMessage();

// could use Debug.Fail without condition
Debug.Assert(condition, GetAssertMessage());
}
#endif
}

You could write your own Assert() wrapper method, decorate it with the
ConditionalAttribute so it only gets called when DEBUG is defined:

public class MyDebug {
[System.Diagnostics.ConditionalAttribute( "DEBUG")]
public static void Assert( bool condition) {
if (!condition) {
string msg = GetAssertMessage();
System.Diagnostics.Debug.Assert(condition, msg);
}
}
}
Now, replace your Debug.Assert() calls with calls to MyDebug.Assert().
GetAssertMessage() will only be evaluated when the assertion condition
fails, and the ConditionalAttribute tells the compiler to not bother
putting the IL for calls to the MyDebug.Assert() method in the assembly
unless DEBUG is defined.

Depending on the deployment requirements of your application, and
whether or not calls to MyDebug.Assert are made from different
assemblies than where MyDebug is implemented, you may want to place the
*body* (not the entire definition) of MyAssert() inside an "#if DEBUG"
block, because the ConditionalAttribute only affects the calls to the
method - the method itself still gets compiled to IL, regardless of the
build type.

You might want to decorate GetAssertMessage() with the conditional
attribute as well, instead of placing it inside an "#if DEBUG" block.

Now that I mentioned that, I'll bet one reason you asked this question
is because you get compiler errors when calls to GetAssertMessage() are
not inside an "#if DEBUG" block. Simply using the ConditionalAttribute
on it will fix that problem.

If your problem is really that actual runtime calls to
GetAssertMessage() are too expensive in a DEBUG build, then you will
probably need to go with my first suggestion.

--
mikeb

Nov 15 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.