5.5. A System Miscellany

In this section we review several useful classes that don't fit into any common category other than miscellaneous. The presentation represents more of a peek than a formal introduction. All of these classes reside directly in the System namespace unless otherwise noted.

5.5.1. The System.Collections.Stack Container

The System.Collections namespace contains a variety of container classes, such as ArrayList (discussed in Section 1.13), Hashtable (Section 1.16), and BitArray (Section 4.9). In general, the container classes store the elements as objects of type object. Value types are boxed and unboxed with each read and write operation. Let's briefly look at the Stack class of the Collections namespace.

The Stack class interface is characterized as follows:

  • Clear() removes all elements from the stack.

  • Contains(object) searches for object in the stack.

  • Count returns the number of elements in the stack.

  • Peek() returns an object at the top without removing it.

  • Pop() removes and returns an object at the top.

  • Push() inserts an object at the top.

  • ToArray() copies the stack elements to an array.

To illustrate how we might use Stack, consider the following problem. When the TextQuery application needs to evaluate a compound query, such as

Alice && ( fiery || untamed )

it finds incomplete operators and independent operands that it needs to tuck away for subsequent retrieval. One way of doing this is to define two stacks—one to hold the current operator, such as && or ||, and one to hold unattached operands—for example,

public class QueryManager
{
      // query operand and operator stacks for
      // processing the user query

      private Stack m_query_stack;
      private Stack m_current_op;
}

When we see Alice in the preceding query, we process it as a NameQuery. There is no operator with which to associate it yet, so we push it onto m_query_stack. When we encounter an operator, such as AndQuery, we pop m_query_stack to retrieve the left AndQuery operand. The right AndQuery operand, however, is not yet available, so we push the AndQuery onto the m_current_op stack—for example,

case ')':
{
   // ...
   if ( m_paren < m_current_op.Count )
   {
          if ( m_query_stack.Count==0 ||
                m_current_op.Count==0 )
          {
                throw new Exception( "Internal Error: " +
                       "Empty query or operator stack " +
                       "for closing right paren!" );
          }

          Query operand = (Query) m_query_stack.Pop();
          Query op      = (Query) m_current_op.Pop();

          op.add_op( operand );
          m_query_stack.Push( op );
    }

    break;
}

There is also a Queue class. It is implemented as a circular array; that is, objects are inserted at one end and removed from the other. When the number of elements reaches its capacity, the capacity is automatically increased. The Queue class interface is characterized as follows:

  • Clear() removes all elements from the queue.

  • Contains(object) searches for object in the queue.

  • Count returns the number of elements in the queue.

  • Peek() returns an object at the front without removing it.

  • Dequeue() removes and returns an object at the front.

  • Enqueue() inserts an object at the back.

  • ToArray() copies the queue elements to an array.

5.5.2. The System.Diagnostics.TraceListener Class

The System.Diagnostics namespace provides a TraceListener family of classes with which the user can turn on and direct diagnostic output. For example, in the WordCount program of Chapter 1, the user determines if and where tracing output should be generated:

if ( m_trace != traceFlags.turnOff )
   switch ( m_trace )
   {
      case traceFlags.toConsole:
          cout = new TextWriterTraceListener( Console.Out );
         Trace.Listeners.Add( cout );

      break;

      case traceFlags.toFile:
          m_tracer =
                 File.CreateText(startupPath + @"	race.txt");
         cout = new TextWriterTraceListener( m_tracer );
         Trace.Listeners.Add( cout );

      break;
   }

The TextWriterTraceListener class is initialized either with a Stream or a TextWriter object. In our example we initialize it either to the console or to a file called trace.txt. We then add it to the Listeners collection monitoring the trace output. The trace output is what we implement—for example,

private void writeWords()
{
    Trace.WriteLine( "!!! WordCount.writeWords: " +
                      m_file_output );
    timer tt = null;

    if ( m_spy ){
            tt = new timer();
            tt.context = "Time to write file ";
            tt.start();
    }

    ArrayList aKeys = new ArrayList( m_words.Keys );
    aKeys.Sort();
    foreach ( string key in aKeys )
    {
          m_writer.WriteLine("{0} : {1}", key, m_words[ key ]);
          Trace.WriteLine( "!!! " + key + " : " +
                           m_words[ key ].ToString() );
    }
    if ( m_spy )
     {
         tt.stop();
         m_times.Add( tt.ToString() );
     }
}

Trace.WriteLine() represents the output to which Listeners is attending. If our user has added something to the Listeners collection within Trace, the WriteLine() output is now directed at that target.

By default, tracing is turned on in Visual Studio for both Debug and Release builds. This means that the tracing code is always present. The benefit of this configuration is that anyone can tap into the code without having to recompile everything. The downside, of course, is that it is always there.

To eliminate the code in the Release build, we can use the Debug class rather than Trace. Debugging is turned off under Release, so no debugging code is generated for Debug methods.

5.5.3. System.Math

The Math class within the System namespace provides static methods for trigonometric (e.g., Cos(), Sin(), Tan()), logarithmic (log(), log10()), and other common mathematical functions (Abs(), Ceiling(), Floor(), Exp(), Min(), Max(), Pow(), Round(), and so on). It defines two fields: E and PI. Here is an example of a Vector class invoking the square root method, Sqrt():

public class Vector
{
      public double length()
          { return Math.Sqrt( length_() ); }

      public double distance( vector v )
          { return Math.Sqrt( distance_( v )); }
      // ...
}

Math is an example of a class that serves primarily as a bucket in which to toss a somewhat random set of operations whose only commonality is that they represent one or another math routine. In a procedural language like C, these static members are presented as independent functions grouped in a library named math. The important thing for you to know about the Math class is just that it exists. Whenever you need a standard math routine, this is the first place to look.

5.5.4. The DateTime Class

The DateTime class represents a date and a time value. Two static properties of the DateTime class are Now, which represents the current date and time, and Today, which retrieves the current date (the time is set to midnight)—for example,

DateTime theDate = DateTime.Now;

To access the time and date as individual strings, we can invoke one of the following DateTime methods:

Console.WriteLine( "The current long date is {0}",
                    theDate.ToLongDateString() );

Console.WriteLine( "The current short date is {0}",
                    theDate.ToShortDateString() );

Console.WriteLine( "The current long time is {0}",
                    theDate.ToLongTimeString() );

Console.WriteLine( "The current short time is {0}",
                    theDate.ToShortTimeString() );

When executed, these statements generate output like the following:

The current long date is Tuesday, February 27, 2001
The current short date is 02/27/2001
The current long time is 14:31:30
The current short time is 14:31

There are also many format strings we can use. The set of DateTime formats is listed in Table 5.1. For example, my favorite is the full format, indicated in code by a capital F:

// generates this format: Tuesday, May 08, 2001 6:23:51 PM
Console.WriteLine( "{0:F}", theDate );

Table 5.1. The DateTime Format Strings
Format Output Description
"{0:d}" 5/8/2001 Short date
"{0:D}" Tuesday, May 08, 2001 Long date
"{0:f}" Tuesday, May 08, 2001 6:23 PM Full (long date + short time)
"{0:F}" Tuesday, May 08, 2001 6:23:51 PM Full (long date + long time)
"{0:g}" 5/8/2001 6:23 PM General (short date + short time)
"{0:G}" 5/8/2001 6:23:51 PM General (short date + long time)
"{0:M}" May 08 Month/day date
"{0:R}" Wed, 09 May 2001 01:23:51 GMT RFC standard
"{0:s}" 2001-05-08T18:23:51 Sortable without time zone
"{0:t}" 6:23 PM Short time
"{0:T}" 6:23:51 PM Long time
"{0:u}" 2001-05-09 01:23:51Z Universal with sortable format
"{0:U}" Wednesday, May 09, 2001 1:23:51 AM Universal with full format
"{0:Y}" May, 2001 Year/month date

The DateTime class supports many instance properties that return different portions of the current DateTime object: Date, Day, Hour, DayOfWeek, DayOfYear, Millisecond, Minute, Month, Second, Ticks, TimeOfDay, and Year.

The DateTime class offers a large number of methods: AddMinutes(), AddMilliseconds(), Parse() (to make a DateTime object from a string), IsLeapYear(), AddDays(), AddHours(), DaysInMonth(), and so on.

There are seven overloaded constructors, including the following four:

DateTime( long Ticks );

DateTime( int year, int month, int day );

DateTime( int year, int month, int day,
          int hour, int min, int sec );

DateTime( int year, int month, int day,
          int hour, int min, int sec,
           int millisecond );

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.172.200