Outputting Debugging Information

Writing text to the Output window at runtime is easy. You simply replace calls to Console.WriteLine() with the required call to write text where you want it. There are two commands you can use to do this:

Debug.WriteLine()
Trace.WriteLine()

These commands function in almost exactly the same way — with one key difference: The first command works in debug builds only; the latter works for release builds as well. In fact, the Debug .WriteLine() command won ’ t even be compiled into a release build; it just disappears, which certainly has its advantages (the compiled code will be smaller, for one thing). You can, in effect, create two versions of your application from a single source file. The debug version displays all kinds of extra diagnostic information, whereas the release version won ’ t have this overhead, and won ’ t display
messages to users that might otherwise be annoying!
 
These functions don ’ t work exactly like Console.WriteLine() . They work with only a single string parameter for the message to output, rather than letting you insert variable values using {X} syntax. This means you must use an alternative technique to embed variable values in strings — for example, the + concatenation. You can also (optionally) supply a second string parameter, which displays a category for the output text. This enables you to see at a glance what output messages are displayed in the Output window, which is useful when similar messages are output from different places in the application.
 
The general output of these functions is as follows:

< category > : < message >

For example, the following statement, which has ” MyFunc ” as the optional category parameter,

Example

Debug.WriteLine("Added 1 to i", "MyFunc");

would result in the following:
MyFunc: Added 1 to i

Example

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] testArray = { 4, 7, 4, 2, 7, 3, 7, 8, 3, 9, 1, 9 };
            int[] maxValIndices;
            int maxVal = Maxima(testArray, out maxValIndices);
            Console.WriteLine("Maximum value {0} found at element indices:",
            maxVal);
            foreach (int index in maxValIndices)
            {
                Console.WriteLine(index);
            }
            Console.ReadKey();
        }
        static int Maxima(int[] integers, out int[] indices)
        {
            Debug.WriteLine("Maximum value search started.");
            indices = new int[1];
            int maxVal = integers[0];
            indices[0] = 0;
            int count = 1;
            Debug.WriteLine(string.Format(
            "Maximum value initialized to {0}, at element index 0.", maxVal));
            for (int i = 1; i < integers.Length; i++)
            {
                Debug.WriteLine(string.Format(
                "Now looking at element at index {0}.", i));
                if (integers[i] > maxVal)
                {
                    maxVal = integers[i];
                    count = 1;
                    indices = new int[1];
                    indices[0] = i;
                    Debug.WriteLine(string.Format(
                    "New maximum found. New value is {0}, at element index {1}.",
                    maxVal, i));
                }
                else
                {
                    if (integers[i] == maxVal)
                    {
                        count++;
                        int[] oldIndices = indices;
                        indices = new int[count];
                        oldIndices.CopyTo(indices, 0);
                        indices[count - 1] = i;
                        Debug.WriteLine(string.Format(
                        "Duplicate maximum found at element index {0}.", i));
                    }
                }
            }
            Trace.WriteLine(string.Format(
            "Maximum value {0} found, with {1} occurrences.", maxVal, count));
            Debug.WriteLine("Maximum value search completed.");
            return maxVal;
        }
    }
}

Explanation

First, an additional using directive appears at the beginning of the code:

using System.Diagnostics;

This simplifies access to the functions discussed earlier because they are contained in the System.Diagnostics namespace. Without this using directive, code such as :

Debug.WriteLine(“Bananas”);

would need further qualification, and would have to be rewritten as :

System.Diagnostics.Debug.WriteLine(“Bananas”);

The using directive keeps your code simple and reduces verbosity. The code in Main() simply initializes a test array of integers called testArray ; it also declares another integer array called maxValIndices to store the index output of Maxima() (the function that performs the calculation), and then calls this function. Once the function returns, the code simply outputs the results.
 
The main body of the function is a loop that cycles through the values in the integers array, omitting the first one because it has already been processed. Each value is compared to the current value of maxVal and ignored if maxVal is greater. If the currently inspected array value is greater than maxVal , then maxVal and indices are changed to reflect this. If the value is equal to maxVal , then count is incremented and a new array is substituted for indices . This new array is one element bigger than the old indices array, containing the new index found. The code for this last piece of functionality is as follows:

if (integers[i] == maxVal)
{
count++;
int[] oldIndices = indices;
indices = new int[count];
oldIndices.CopyTo(indices, 0);
indices[count - 1] = i;
Debug.WriteLine(string.Format(
"Duplicate maximum found at element index {0}.", i));
}

This works by backing up the old indices array into oldIndices , an integer array local to this if code block. Note that the values in oldIndices are copied into the new indices array using the < array > .CopyTo() function. This function simply takes a target array and an index to use for the first element to copy to and pastes all values into the target array.
 
Throughout the code, various pieces of text are output using the Debug.WriteLine() and Trace.WriteLine() functions. These functions use the string.Format() function to embed variable values in strings in the same way as Console.WriteLine() . This is slightly more efficient than using
the + concatenation operator.
 
When you run the application in Debug mode, you see a complete record of the steps taken in the loop that give you the result. In Release mode, you see just the result of the calculation, because no calls to Debug.WriteLine() are made in release builds. In addition to these WriteLine() functions are a few more you should be aware of. To start with, there are equivalents to Console.Write() :

Debug.Write()
Trace.Write()

Both functions use the same syntax as the WriteLine() functions (one or two parameters, with a message and an optional category), but differ in that they don ’ t add end – of – line characters. There are also the following commands:
Debug.WriteLineIf()
Trace.WriteLineIf()
Debug.WriteIf()
Trace.WriteIf()

Each of these has the same parameters as the non – If counterparts, with the addition of an extra, mandatory parameter that precedes them in the parameter list. This parameter takes a Boolean value (or an expression that evaluates to a Boolean value) and results in the function only writing text if this value evaluates to true . You can use these functions to conditionally output text to the Output window.