Скачиваний:
64
Добавлен:
15.03.2015
Размер:
4.31 Mб
Скачать

638

Extreme C#

PART IV

other of these methods, directive or compilation option, enables debugging, but they both are not required together. If neither of these, directive or compilation option, are present, the Debug class does not operate, and there would be no output.

LISTING 31.2 Compilation Instructions for Listing 31.1

csc /d:DEBUG PlainDebugDemo.cs

Conditional Debugging

A program’s capability to turn debugging on and off as needed is called conditional debugging. During development, output from debugging can clutter up normal output or force paths of execution that isn’t necessary on every run. The System.Diagnostics namespace has both attributes and switches to turn debugging on and off as necessary. Listing 31.3 shows how to use attributes to control conditional debugging.

LISTING 31.3 Debugging with Conditional Attributes: ConditionalDebugDemo.cs

#define DEBUG

using System;

using System.Diagnostics;

///<summary>

///Conditional Debug Demo.

///</summary>

class ConditionalDebugDemo

{

static bool Debugging = true;

[Conditional(“DEBUG”)]

static void SetupDebugListener()

{

TextWriterTraceListener myListener =

new TextWriterTraceListener(Console.Out);

Debug.Listeners.Add(myListener);

}

[Conditional(“DEBUG”)] static void CheckState()

{

Debug.WriteLineIf(Debugging, “Debug: Entered CheckState()”);

}

LISTING 31.3 continued

static void Main(string[] args)

{

SetupDebugListener();

CheckState();

}

}

Runtime Debugging

CHAPTER 31

639

31

UNTIMER

EBUGGINGD

And here’s the output:

Debug: Entered CheckState()

Two features of Listing 31.3 are of primary interest: the Conditional attribute and a Boolean condition on output. The Conditional attribute is placed at the beginning of a method that can be turned on and off at will. The condition causing the method to be invoked is either the #define DEBUG directive at the top of the listing or the command line /d:DEBUG option, shown in Listing 31.4. If neither of these, directive or command line option, is present, the methods with the Conditional attribute are invoked when called by the Main() method.

LISTING 31.4 Compilation Instructions for Listing 31.3

csc /d:DEBUG ConditionalDebugDemo.cs

The second item of interest in Listing 31.3 is the Boolean condition parameter of the

WriteLineIf() method in the CheckState() method. The WriteLineIf() method of the

Debug class has a first parameter that takes a bool. In the example, the static class field Debugging is used as an argument. It’s set to true, but had it been set to false, there would have been no output.

The examples presented so far expect that the code will be recompiled to turn debugging on and off. In a development environment, this is fine. However, in production, such luxury is not likely to be available. That’s why the example in Listing 31.5 uses the

BooleanSwitch and Trace classes.

LISTING 31.5 Implementing Debugging with a Boolean Switch:

BooleanSwitchDemo.cs

using System;

using System.Diagnostics;

///<summary>

///BooleanSwitch Demo.

640

Extreme C#

PART IV

LISTING 31.5 continued

/// </summary>

class BooleanSwitchDemo

{

BooleanSwitch traceOutput = new BooleanSwitch(“TraceOutput”, “Boolean Switch Demo”);

void SetupDebugListener()

{

TextWriterTraceListener myListener =

new TextWriterTraceListener(Console.Out);

Trace.Listeners.Add(myListener);

}

void CheckState()

{

Trace.WriteLineIf(traceOutput.Enabled,

“Debug: Entered CheckState()”);

}

static void Main(string[] args)

{

BooleanSwitchDemo bsd = new BooleanSwitchDemo();

bsd.SetupDebugListener();

bsd.CheckState();

}

}

And the output is:

Debug: Entered CheckState()

The CheckState() method of Listing 31.5 is similar to the same method in Listing 31.3, except that the WriteLineIf() method uses the Enabled property of a BooleanSwitch object as its first parameter. The BooleanSwitch class is instantiated with a first parameter as the display name and a second parameter as a description.

An entry must be added to the program’s configuration file to turn on tracing. Listing 31.6 shows how to add the BooleanSwitch display name entry into the configuration file. The configuration file must have the same name as the executable with a .config extension.

LISTING 31.6 BooleanSwitch entry in Configuration File: BooleanSwitchDemo.config

<configuration>

<system.diagnostics>

LISTING 31.6 continued

<switches>

<add name=”TraceOutput” value=”1” /> </switches>

</system.diagnostics>

</configuration>

LISTING 31.7 Compilation Instructions for Listing 31.5

csc /d:TRACE BooleanSwitchDemo.cs

Runtime Debugging

CHAPTER 31

641

31

UNTIMER

EBUGGINGD

Runtime Tracing

Runtime tracing is the capability to perform debug tracing while a program is running. Sometimes it’s necessary to have more control over what debugging information is displayed. Specific types of problems often indicate what information should be displayed in trace output. The TraceSwitch class is similar to the BooleanSwitch class in that it allows you to create a configuration file or set an environment variable. However, its real value comes in being able to specify a finer degree of granularity in determining what information is displayed. The example in Listing 31.8 demonstrates how to use the

TraceSwitch class.

LISTING 31.8 TraceSwitch Class Demo: TraceSwitchDemo.cs

using System;

using System.Diagnostics;

///<summary>

///TraceSwitch Demo.

///</summary>

class TraceSwitchDemo

{

public static TraceSwitch traceOutput = new TraceSwitch(“TraceOutput”, “TraceSwitch Demo”);

void SetupDebugListener()

{

TextWriterTraceListener myListener =

new TextWriterTraceListener(Console.Out);

Trace.Listeners.Add(myListener);

}

642

Extreme C#

PART IV

LISTING 31.8 continued

void CheckState()

{

Trace.WriteLineIf(traceOutput.TraceInfo,

“Trace: Entered CheckState()”);

}

static void Main(string[] args)

{

TraceSwitchDemo tsd = new TraceSwitchDemo();

tsd.SetupDebugListener();

tsd.CheckState();

}

}

And here’s the output:

Trace: Entered CheckState()

The implementation of the TraceSwitch is similar to the BooleanSwitch, except that the first parameter to the WriteLineIf() method in the CheckState() method is the TraceInfo property of the TraceSwitch class. This parameter can be any of the possible values corresponding to a member of the TraceLevel enum, shown in Table 31.1.

TABLE 31.1 TraceLevel Enum

TraceLevel enum

Description

Verbose

Output everything

Info

Output info, error, and warning

Warning

Output error and warning

Error

Output error

Off

Output nothing

 

 

TraceSwitch must be set in a configuration file. Values may be from 0 to 4 with Verbose equal to 4 and descending to Off, which is equal to 0. It’s possible to create a custom switch by inheriting the Switch class and defining Boolean properties with your own unique names that map to the available members of the TraceLevel enum. The configuration file in Listing 31.9 has TraceOutput set to 3, which causes evaluation of

TraceInfo to return true.