Google Answers Logo
View Question
 
Q: #define out all occurrences of a function in c# ( Answered 4 out of 5 stars,   0 Comments )
Question  
Subject: #define out all occurrences of a function in c#
Category: Computers > Programming
Asked by: mcc03-ga
List Price: $10.00
Posted: 10 Aug 2003 08:56 PDT
Expires: 09 Sep 2003 08:56 PDT
Question ID: 242138
I've written some code in the C# programming language. I have a lot of
calls to a function that prints out some debugging information. I
would like to occasionally remove all calls to these functions when I
want the program to run quickly (when I'm measuring how fast it runs)
but I want the calls to be in when I'm debugging.
More detail: I have a class called MyDebug with a member called Trace.
I periodically call MyDebug.Trace(“string with debugging info...”).

Solutions that aren't sufficient:
- I don't want to have to comment out all calls to this function every
time I want to do performance analysis, because there are LOTS of
calls and this would take a long time.
- I can't simply modify the function to return null instead of
printing, because the arguments to the function take a lot of overhead
to compute. For example, I may call MyDebug.Trace(“val1
“+val1.ToString()+”val2”+val2.ToString()), which has to concatenate
several strings together, which causes a lot of overhead. I don’t want
the argument to be evaluated in the first place.

I suspect there must be a solution for this, since C++ has a nice way
to solve this:
(from http://www-subatech.in2p3.fr/~photons/subatech/soft/carnac/CPP-DEB-2.shtml)
#define assert(THETEST) ((void)0)
makes it so all calls to assert go away. 

My question then is, how can I remove all calls to a function in C#,
without commenting the calls out (takes too long) and so that the
arguments aren’t evaluated?

Thanks a lot for your help.
Answer  
Subject: Re: #define out all occurrences of a function in c#
Answered By: cyclometh-ga on 10 Aug 2003 16:45 PDT
Rated:4 out of 5 stars
 
Hi mcc03-ga!

There are actually several alternatives available to you for
accomplishing the task you are attempting, which is to conditionally
execute certain code based on whether you are in debug mode or not.

The first method, which is C#'s equivalent of the C++ method you
provided a link to, is conditional compilation directives. In C#, you
can have some code like so:

public void MyMethod()
{

  MessageBox.Show("This will display in any case.");
#if DEBUG

  MessageBox.Show("In Debug Mode.");

#else

  MessageBox.Show("In Release Mode");

#endif
}

The #if directive will only compile one branch or the other of the
#if...#endif construct shown. The DEBUG constant is one that is
automatically defined by the .NET IDE if you are in a Debug
configuration. You can modify which compiler constants are defined
automatically by opening the "Project Properties" dialog, selecting
"Configuration Properties", and the "Build" node. In the "Code
Generation" section of this property page is a property called
"Conditional Compilation Constants", which by default for the Debug
configuration is set to "DEBUG;TRACE". You can additional constants by
seperating them with a semicolon character.

You can also define your own compilation constants using the #define
directive:

#define MYCONSTANT[=value]

The portion in brackets is optional, leaving them out makes the
constant assume a value of True or 1. Note: Such directives must be
placed at the top of a file, before any tokens in the file such as
namespace, class, or other declarations.

With the custom #define shown above, we can use the same code we did
before, with appropriate modifications:

public void MyMethod()
{

  MessageBox.Show("This will display in any case.");
#if MYCONSTANT

  MessageBox.Show("My constant is defined.");

#else

  MessageBox.Show("My constant is not defined.");

#endif
}

You can do quite a bit with C# compiler directives. There is a lot of
good information available from MSDN here:

[MSDN C# Compiler Directives Reference]
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vclrfPreprocessorDirectives.asp

(This URL is long, so it may wrap.)

Essentially, using this technique, you could wrap all your calls to
your function in these directives, i.e.:

#if DEBUG
MyDebug.Trace(arg1, ...argn);
#endif

Which would require additional code, but only once. After that time,
you would no longer need to worry about these function calls. If you
wanted a simpler way to approach it, you could write a global function
which received the arguments you refer to and does the expensive work
of all that string manipulation, and simply call that method from your
code in place of directly calling your trace method. This global
method could do the required work and then call your tracing code, or
it could simply return. This could be done with one compilation
directive, rather than one for every call to your tracing code.

However, the C# language and the .NET Framework provide what may be a
more suitable mechanism for your needs- the Debug and Trace classes.
These classes are part of the Framework and are available to all
Framework languages, including VB.NET and C#.

The two classes are essentially the same in their interface, with the
same methods and properties, but they have slightly different behavior
at run-time.

With the Debug class, you can call its methods anywhere in your code,
but they will only be executed if your program is in debug mode. For
example, both the Debug and Trace classes have an Assert method, which
is static:

Debug.Assert(condition);

if condition is false, an exception is thrown and you can figure out
what the problem is. The Assert method can also be called with
additional arguments, such as messages and so on, to accomodate
various situations.

The Trace class also has an Assert method, as well as methods such as
WriteLine and WriteLineIf. With the Trace class (and the Debug class),
you can use the built-in support of the Framework to support tracing
of your code, like so:

public void MyMethod()
{
Trace.WriteLine("Entering MyMethod");
//do some work.
}

For conditional tracing, you can use Trace.WriteLineIf() and a
TraceSwitch. You define TraceSwitch properties in App.Config, like so:

<system.diagnostics>
  <switches>
    <add name="MyTrace" value="4"/>
  </switches>
</system.diagnostics>

In your code, you can create a new instance of a TraceSwitch class:

myTrace TraceSwitch=new TraceSwitch("MyTrace", "My trace switch");

The string "MyTrace" matches the one defined in App.Config, which in
this case sets its tracing level to 4, Verbose. There are 5 trace
levels: 0- Off, 1-Error, 2-Warning, 3-Info, and 4-Verbose. You can use
these levels to write conditional tracing code into your program, like
so:

public void MyMethod()
{
//The WriteLineIf method will only execute 
//if the first argument evaluates to True.
Trace.WriteLineIf(myTrace.TraceVerbose, "Entering MyMethod()");
//do some work.
}

I generally declare my TraceSwitch instances as public static members
of some common library, so they only need to be created once, and are
accessible to all my code. The nice thing about the WriteLineIf()
function is that it only evaluates the arguments passed to it if the
first argument is true.

It also provides a nice logging facility, as you can set up
TraceListeners to write not only to the IDE output window, but to the
Windows event log, or to a text file.

For a good introduction to Tracing, Debugging, and Performance
monitoring, see the following MSDN link:

[Tracing and Instrumenting Applications in Visual Basic and C#]
http://msdn.microsoft.com/library/en-us/vbcon/html/vboriInstrumentationTechniquesDebugTraceForNETFramework.asp

(another potentially long URL, so it may wrap).

I sincerely hope this information was of use to you, and please let me
know if I can provide any clarification of my answer.

Best regards,

Cyclometh (cyclometh-ga)

Request for Answer Clarification by mcc03-ga on 11 Aug 2003 02:52 PDT
Thanks a lot for the great answer! I ended up using a solution I found
somewhere else:
http://groups.google.com/groups?dq=&hl=en&lr=&ie=UTF-8&selm=3f367bdc%241%40clarion.carno.net.au

I preferred this solution, since seems to be more clean for my problem
(don't need to change my code very much). I'm posting this solution
here in case it helps someone else...

Thanks again for your help.

Clarification of Answer by cyclometh-ga on 11 Aug 2003 03:53 PDT
I must admit, I wasn't familiar with that particular way of decorating
a method before this. I drew on my own personal knowledge for the
answer, rather than searching for it, so I've learned something as
well. :) I'll be sure and remember it myself in the future. In point
of fact, I have a project I'm working on that may benefit from it.

I'm glad you found an answer that works for you, and I hope that even
if my answer wasn't the precise one you needed, that the information I
provided proves of some use.

Thanks again and regards,

Cyclometh (cyclometh-ga)
mcc03-ga rated this answer:4 out of 5 stars
I found a more accurate answer elsewhere on my own:
http://groups.google.com/groups?dq=&hl=en&lr=&ie=UTF-8&selm=3f367bdc%241%40clarion.carno.net.au

Comments  
There are no comments at this time.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy