Chris Rathman / Chris.Rathman@tx.rr.com

/************************************************************************
 *                                                                      *
 * Reserved Words:                                                      *
 *                                                                      *
 *    C#:                                                               *
 *       abstract        event           namespace       static         *
 *       as              explicit        new             string         *
 *       base            extern          null            struct         *
 *       bool            false           object          switch         *
 *       break           finally         operator        this           *
 *       byte            fixed           out             throw          *
 *       case            float           override        true           *
 *       catch           for             params          try            *
 *       char            foreach         private         typeof         *
 *       checked         get             protected       uint           *
 *       class           goto            public          ulong          *
 *       const           if              readonly        unchecked      *
 *       continue        implicit        ref             unsafe         *
 *       decimal         in              return          ushort         *
 *       default         int             sbyte           using          *
 *       delegate        interface       sealed          value          *
 *       do              internal        set             virtual        *
 *       double          is              short           void           *
 *       else            lock            sizeof          volatile       *
 *       enum            long            stackalloc      while          *
 *                                                                      *
 ************************************************************************/

/************************************************************************
 *                                                                      *
 * FCL - Framework Base Class Library:                                  *
 *    Microsoft                           Microsoft                     *
 *      *CSharp                              Vsa                        *
 *      *JScript                             Win32                      *
 *       VisualBasic                                                    *
 *    System                              System                        *
 *       CodeDom                             Globalization              *
 *          Compiler                         IO                         *
 *       Collections                            IsolatedStorage         *
 *          Specialized                      Management                 *
 *       ComponentModel                         Instrumentation         *
 *          Design                           Messaging                  *
 *             Serialization                 Net                        *
 *       Configuration                          Sockets                 *
 *          Assemblies                       Reflection                 *
 *          Install                             Emit                    *
 *       Data                                Resources                  *
 *          Common                           Security                   *
 *          Odbc                                Cryptography            *
 *          OleDb                                  X509Certificates     *
 *          OracleClient                           Xml                  *
 *          SqlClient                           Permissions             *
 *          SqlServerCE                         Policy                  *
 *          SqlTypes                            Principal               *
 *       Diagnostics                         ServiceProcess             *
 *          SymbolStore                      String                     *
 *       DirectoryServices                   Text                       *
 *       Drawing                                RegularExpressions      *
 *          Design                           Threading                  *
 *          Drawing2D                        Timers                     *
 *          Imaging                          Web                        *
 *          Printing                            Caching                 *
 *          Text                                Configuration           *
 *       EnterpriseServices                     Hosting                 *
 *          CompensatingResourceManager         Mail                    *
 *          Internal                            Mobile                  *
 *       RunTime                                Security                *
 *          CompilerServices                    Services                *
 *          InteropServices                        Configuration        *
 *             CustomMarshalers                    Description          *
 *             Expando                             Discovery            *
 *          Remoting                               Protocols            *
 *             Activation                       SessionState            *
 *             Channels                         UI                      *
 *                Http                             Design               *
 *                Tcp                              Design.WebControls   *
 *             Contexts                            HtmlControls         *
 *             Lifetime                            MobileControls       *
 *             Messaging                              Adapters          *
 *             Metadata                            WebControls          *
 *                W3cXsd2001                 Windows                    *
 *             MetadataServices                 Forms                   *
 *             Proxies                             Design               *
 *             Services                      Xml                        *
 *          Serialization                       Schema                  *
 *             Formatters                       Serialization           *
 *                Binary                        XPath                   *
 *                Soap                          Xsl                     *
 *                                                                      *
 ************************************************************************/

/************************************************************************
 *                                                                      *
 * Documentation Comments:                                              *
 *                                                                      *
 ************************************************************************/
 /// <summary>
 /// Summary of a Member
 /// </summary>
 /// <remarks>Description of a type</remarks>
 /// <param name="pname">Description for method parameter</param>
 /// <returns>Description of return value</returns>
 /// <exception cref="IndexOutOfRangeException">Description of Exceptions that may be thrown</exception>
 /// <permission cref="public">Description of permission requirements</permission>
 /// <example>Example Description</example>
 /// <code>Syntax x = new Syntax();</code>
 /// <seealso cref="System.IO">Document Cross Reference</seealso>
 /// <see cref="System.IO">Inline Document Cross Reference</see>
 /// <value>Description of Property Value</value>
 /// <paramref name="prname">Parameter name within descriptive text</paramref>
 /// <include file="documentation.xml" path="/">External documentation file</include>
 /// <mytag>User Defined Tags</mytag>

/***************************************************************************
 *                                                                         *
 * Preprocessor Defines:                                                   *
 *                                                                         *
 ***************************************************************************/
#define DEBUG                                // defines/undefines must be first directives in file
#undef DEBUG

/***************************************************************************
 *                                                                         *
 * Using NameSpace References:                                             *
 *                                                                         *
 ***************************************************************************/
using System;                                // allow simple access to classes within namespace without full name
using socks = System.Net.Sockets;            // aliasing namespace
using txt = System.String;                   // aliasing type

/***************************************************************************
 *                                                                         *
 * NameSpace Definition:                                                   *
 *                                                                         *
 ***************************************************************************/
namespace Fred { namespace Hank { } }     // namespaces may be nested
namespace Fred.Hank { }                   // shortcut for nested namespaces

namespace Test {

   /************************************************************************
    *                                                                      *
    * Classes:                                                             *
    *                                                                      *
    ************************************************************************/
   class Syntax {

      /*********************************************************************
       *                                                                   *
       * Access Modifiers:                                                 *
       *                                                                   *
       *********************************************************************/
      int mydefault;                         // private by default
      public int mypublic;                   // visible to any class
      private int myprivate;                 // visible only to this class
      protected int myprotected;             // visible only to this class and subclasses
      internal int myinternal;               // visible to any class in this assembly
      protected internal int myprotint;      // protected or internal visibility

      // class, struct, properties and indexers can be set with: abstract, virtual, override, sealed

      /*********************************************************************
       *                                                                   *
       * Properties:                                                       *
       *                                                                   *
       *********************************************************************/
                                             // instance variables (properties) default to 0, false, or null
      const double PI = 3.14;                // constant - c# does not have static final
      static int objcount = 0;               // one variable shared by all instances of the class
      readonly int xstat = 123;              // readonly variable
      volatile int myvolatile;               // volatile variable

      enum Colors:byte{Red=0,Blue=1,Green=2} // enumerations are another form of constants

      public int MyProperty {                // properties using get/set
         get { return mydefault;  }
         set { mydefault = value; }
      }

      static Syntax() {                      // static initialization block - at time the class is first loaded
         System.Console.WriteLine("Static Block");
      }

      Square xd = new Square(2.0);           // objects can be allocated outside of methods

      /*********************************************************************
       *                                                                   *
       * Application Entry Point:                                          *
       *                                                                   *
       *********************************************************************/
      // Main is the entry for the program
      static void Main(string[] args) {
         // stream io
         System.Console.WriteLine("Hello World");
         System.Console.WriteLine("Hello World {0}", System.DateTime.Now);
         for (int i = 0; i < args.Length; i++) {
            System.Console.WriteLine(args[i]);
         }

         // make an instance of this class
         Syntax syntax_obj = new Syntax();

         syntax_obj = null;

         // try a different constructor
         syntax_obj = new Syntax("Hello");

         // using variation to ensure earliest call of Dispose() - class must implement IDisposable
         using (System.Drawing.Font theFont = new System.Drawing.Font("Arial", 10.0F)) {
            // do whatever you want here - compiler calls dispose at end
         }

         // make a structure instance
         Location loc1 = new Location(1,2);
         System.Console.WriteLine(loc1);
      }

      /*********************************************************************
       *                                                                   *
       * Constructors:                                                     *
       *                                                                   *
       *********************************************************************/
      public Syntax() {                      // constructors do not return a value and have the same name as the class
         Types();
         Operators();
         Flow();
         Preprocessor();
         Functions();
         Objects();
         Strings();
         StringBuilders();
         RegEx();
         Arrays();
         Indexers();
         Collect();
         Exceptions();
         Pointers();
         Delegates();
         FileIO();
         Threads();
         Reflections();
         Databases();
         Networking();
         InnerClass x10 = new InnerClass();
         OuterClass x11 = new OuterClass();
      }

      public Syntax(String s) { }

      /*********************************************************************
       *                                                                   *
       * Destructors:                                                      *
       *                                                                   *
       *********************************************************************/
      ~Syntax() {
         // finalize called after object goes out of scope and the garbage collection is performed (useless!)
         System.Console.WriteLine("destructor");

         // Note: this is just syntactic sugar for
         //    protected override void Finalize() { try { } finally { base.Finalize(); } }
      }

      /*********************************************************************
       *                                                                   *
       * Built-In Value Types:                                             *
       *                                                                   *
       *********************************************************************/
      private void Types() {                 // local variables are not automatically initialized
         sbyte   aSByte;                     // System.SByte   - 8-bit signed
         byte    aByte;                      // System.Byte    - 8-bit unsigned
         short   aShort;                     // System.Int16   - 16-bit signed
         ushort  aUShort;                    // System.UInt16  - 16-bit unsigned
         int     aInt;                       // System.Int32   - 32-bit signed
         uint    aUInt;                      // System.UInt32  - 32-bit unsigned
         long    aLong;                      // System.Int64   - 64-bit signed
         ulong   aULong;                     // System.UInt64  - 64-bit unsigned
         float   aFloat;                     // System.Single  - 32-bit ieee
         double  aDouble;                    // System.Double  - 64-bit ieee
         decimal aDecimal;                   // System.Decimal - 28 digit fixed precision
         char    aChar;                      // System.Char    - 16-bit unicode
         bool    aBool;                      // System.Boolean - true|false

         int i = 0;                          // initialize when declared
         int j = i - 1;                      // autoinit may contain expressions

         aSByte   = 0;                       // int constant
         aByte    = 0;
         aShort   = 0;
         aUShort  = 0;
         aInt     = 0;
         aUInt    = 0;
         aLong    = 0;
         aULong   = 0;
         aFloat   = 0;
         aDouble  = 0;
         aDecimal = 0;
         aChar    = 'a';                     // character constant
         aBool    = false;                   // boolean constant

         aByte = 0xF;                        // hex notation (no octal?)
         aUInt = 2U;                         // unsigned int constant
         aLong = 2L;                         // long constant
         aULong = 2UL;                       // unsigned long constant
         aFloat = 4.0F;                      // float constant
         aFloat = -9.99F;                    // negative float constant
         aDouble = 4.0E2;                    // scientific notation
         aDecimal = 123.456M;                // decimal constant

         aChar = '\u0001';                   // hex unicode character (www.unicode.com)
         aChar = '\'';                       // single quote
         aChar = '\"';                       // double qoute
         aChar = '\\';                       // backslash
         aChar = '\0';                       // null
         aChar = '\a';                       // alert
         aChar = '\b';                       // backspace
         aChar = '\f';                       // form feed
         aChar = '\n';                       // new line
         aChar = '\r';                       // carriage return
         aChar = '\t';                       // tab
         aChar = '\v';                       // vertical tab

         aInt = (int)'A';                    // equivalent to ascii()
         aChar = (char)65;                   // equivalent to char()

         // C# does less auto-casting than C++
         aSByte += 1;                     aByte += 1;                   // combined operators not require cast
         aSByte = (sbyte)(aSByte + 1);    aByte = (byte)(aByte + 1);    // all byte/short math is done in int - plus (+) autocasts to int
         aSByte = aSByte;                 aByte = (byte)aSByte;
         aSByte = (sbyte)aByte;           aByte = aByte;
         aSByte = (sbyte)aShort;          aByte = (byte)aShort;
         aSByte = (sbyte)aUShort;         aByte = (byte)aUShort;
         aSByte = (sbyte)aInt;            aByte = (byte)aInt;
         aSByte = (sbyte)aUInt;           aByte = (byte)aUInt;
         aSByte = (sbyte)aLong;           aByte = (byte)aLong;
         aSByte = (sbyte)aULong;          aByte = (byte)aULong;
         aSByte = (sbyte)aFloat;          aByte = (byte)aFloat;         // truncation on the floating point numbers
         aSByte = (sbyte)aDouble;         aByte = (byte)aDouble;
         aSByte = (sbyte)aDecimal;        aByte = (byte)aDecimal;
         aSByte = (sbyte)aChar;           aByte = (byte)aChar;

         aShort += 1;                     aUShort += 1;
         aShort = (short)(aShort + 1);    aUShort = (ushort)(aUShort + 1);
         aShort = aSByte;                 aUShort = (ushort)aSByte;
         aShort = aByte;                  aUShort = aByte;
         aShort = aShort;                 aUShort = (ushort)aShort;
         aShort = (short)aUShort;         aUShort = aUShort;
         aShort = (short)aInt;            aUShort = (ushort)aInt;
         aShort = (short)aUInt;           aUShort = (ushort)aUInt;
         aShort = (short)aLong;           aUShort = (ushort)aLong;
         aShort = (short)aULong;          aUShort = (ushort)aULong;
         aShort = (short)aFloat;          aUShort = (ushort)aFloat;
         aShort = (short)aDouble;         aUShort = (ushort)aDouble;
         aShort = (short)aDecimal;        aUShort = (ushort)aDecimal;
         aShort = (short)aChar;           aUShort = aChar;

         aInt += 1;                       aUInt += 1;
         aInt = (aInt + 1);               aUInt = (aUInt + 1);
         aInt = aSByte;                   aUInt = (uint)aSByte;
         aInt = aByte;                    aUInt = aByte;
         aInt = aShort;                   aUInt = (uint)aShort;
         aInt = aUShort;                  aUInt = aUShort;
         aInt = aInt;                     aUInt = (uint)aInt;
         aInt = (int)aUInt;               aUInt = aUInt;
         aInt = (int)aLong;               aUInt = (uint)aLong;
         aInt = (int)aULong;              aUInt = (uint)aULong;
         aInt = (int)aFloat;              aUInt = (uint)aFloat;
         aInt = (int)aDouble;             aUInt = (uint)aDouble;
         aInt = (int)aDecimal;            aUInt = (uint)aDecimal;
         aInt = aChar;                    aUInt = aChar;

         aLong += 1;                      aULong += 1;
         aLong = (aLong + 1);             aULong = (aULong + 1);
         aLong = aSByte;                  aULong = (ulong)aSByte;
         aLong = aByte;                   aULong = aByte;
         aLong = aShort;                  aULong = (ulong)aShort;
         aLong = aUShort;                 aULong = aUShort;
         aLong = aInt;                    aULong = (ulong)aInt;
         aLong = aUInt;                   aULong = aUInt;
         aLong = aLong;                   aULong = (ulong)aLong;
         aLong = (long)aULong;            aULong = aULong;
         aLong = (long)aFloat;            aULong = (ulong)aFloat;
         aLong = (long)aDouble;           aULong = (ulong)aDouble;
         aLong = (long)aDecimal;          aULong = (ulong)aDecimal;
         aLong = aChar;                   aULong = aChar;

         aFloat += 1;                     aDouble += 1;
         aFloat = (aFloat + 1);           aDouble = (aDouble + 1);
         aFloat = aSByte;                 aDouble = aSByte;
         aFloat = aByte;                  aDouble = aByte;
         aFloat = aShort;                 aDouble = aShort;
         aFloat = aUShort;                aDouble = aUShort;
         aFloat = aInt;                   aDouble = aInt;
         aFloat = aUInt;                  aDouble = aUInt;
         aFloat = aLong;                  aDouble = aLong;
         aFloat = aULong;                 aDouble = aULong;
         aFloat = aFloat;                 aDouble = aFloat;
         aFloat = (float)aDouble;         aDouble = aDouble;
         aFloat = (float)aDecimal;        aDouble = (float)aDecimal;
         aFloat = aChar;                  aDouble = aChar;

         aDecimal += 1;                   aChar += 'a';
         aDecimal = (aDecimal + 1);       aChar = (char)(aUShort + 1);
         aDecimal = aSByte;               aChar = (char)aSByte;
         aDecimal = aByte;                aChar = (char)aByte;
         aDecimal = aShort;               aChar = (char)aShort;
         aDecimal = aUShort;              aChar = (char)aUShort;
         aDecimal = aInt;                 aChar = (char)aInt;
         aDecimal = aUInt;                aChar = (char)aUInt;
         aDecimal = aLong;                aChar = (char)aLong;
         aDecimal = aULong;               aChar = (char)aULong;
         aDecimal = (decimal)aFloat;      aChar = (char)aFloat;
         aDecimal = (decimal)aDouble;     aChar = (char)aDouble;
         aDecimal = aDecimal;             aChar = (char)aDecimal;
         aDecimal = aChar;                aChar = aChar;

         aBool = !false;                     // can't cast other types to or from boolean type

         object o = 123;                     // automatic boxing
         int z = (int)o;                     // unboxing must be explicit
      }

      /*********************************************************************
       *                                                                   *
       * Operators:                                                        *
       *         ()  grouping                <<  left shift                *
       *          .  member access           >>  right shift               *
       *         ->  pointer member access    <  less than                 *
       *         ()  method call              >  greater than              *
       *         []  indexing                <=  less than or equal        *
       *         ++  post increment          >=  greater than or equal     *
       *         --  post decrement          is  type compatibility        *
       *        new  constructor call        as  conditional type convert  *
       * stackalloc  array stack allocate    ==  equal                     *
       *     typeof  type                    !=  not equal                 *
       *     sizeof  size                     &  bitwise and / logical and *
       *    checked  arithmetic check on      ^  bitwise xor               *
       *  unchecked  arithmetic check off     |  bitwise or                *
       *          +  unary plus              &&  logical and               *
       *          -  unary minus             ||  logical or                *
       *          !  logical not             ?:  ternary conditional       *
       *          ~  one's complement         =  assign                    *
       *         ++  pre increment           *=  compound assign           *
       *         --  pre decrement           /=                            *
       *     (type)  type cast               %=                            *
       *          *  value at address        +=                            *
       *          &  address of value       <-=                            *
       *          *  multiply               ><=                            *
       *          /  divide                  >=                            *
       *          %  modulus                 &=                            *
       *          +  add                     ^=                            *
       *          -  subtract                |=                            *
       *                                                                   *
       *********************************************************************/
      private void Operators() {
         bool b;
         int i;
         int j;
         byte k = 10;
         float x;
         string s = "Test";

         i = 1;                              // simple asignment: i = 1;
         i = j = 3;                          // compound assignment: j = 3; i = j;
         i = (j = 1) + 2;                    // parenthesis precedence: j = 1; i = j + 2;

         i = 3 + 2;                          // add: i = 5;
         i = (3) % (2);                      // mod: i = 2;

         x = (int)3.14;                      // cast operator: i = 3;
         x = 2 / 3;                          // integer divide: x = 0
         k = (byte)-k;                       // unary plus/minus always converts byte/short/char to an int
         checked { i = j + 1; }              // check for overflow
         unchecked { i = j + 1; }            // ignore overflow

         i = ++j;                            // pre-increment: j = j + 1; i = j;
         i = --j;                            // pre-decrement: j = j - 1; i = j;
         i = j++;                            // post-increment: i = j; j = j + 1;
         i = j--;                            // post-increment: i = j; j = j - 1;

                                             // compound assignment operators - always does autocast
         i += j;                             // i = i + j;
         i -= j;                             // i = i - j;
         i *= j;                             // i = i * j;
         i /= j;                             // i = i / j;
         i %= j;                             // i = i % j;
         i <<= j;                            // i = i << j;
         i >>= j;                            // i = i >> j;
         i &= j;                             // i = i & j;
         i ^= j;                             // i = i ^ j;
         i |= j;                             // i = i | j;

                                             // only boolean var may receive boolean op result
         b = (i == 0);                       // equal
         b = (i < j);                        // less than
         b = (i <= j);                       // less than or equal
         b = (i > j);                        // greater than
         b = (i >= j);                       // greater than or equal
         b = (i != j);                       // not equal

         b = !b;                             // not operator
         b = ((i > 0) && (i < j));           // logical and
         b = ((i > 0) || (i < j));           // logical or
         b = ((i > 0) & (i < j));            // logical and - always perform both tests
         b = ((i > 0) | (i < j));            // logical or - always perform both tests

         i = j & 1;                          // bitwise and
         i = j ^ 1;                          // bitwise xor
         i = j | 1;                          // bitwise or

         b = "abc" is string;                // ask object if it has class or interface methods
         s = "abc" as string;                // test type and cast (null if not compatible)
      }

      /*********************************************************************
       *                                                                   *
       * Flow Control:                                                     *
       *                                                                   *
       *********************************************************************/
      private bool Flow() {
         int i = 10;
         int j = 10;
         bool b = true;

         {                                   // variable scope is limited to block in which it is declared
            byte localScope = 3;             // C# requires local scope variable names to be unique
         }

         if (b) {                            // if then else
            j = 1;
         } else {
            j = 2;
         }

         j = (i!=0)? 10 : 20;                // ternary operator

         while (i != 0) {                    // while loop
            i = i - 1;
            if (b) continue;
            break;
         }

         do {                                // do while loop
            i = i + 1;
            if (b) continue;
            break;
         } while (i < 10);

         for (i = 0; i < 4; i++) {           // for loop  - comma operator allowed in initialize and increment
            j = j + 1;                       // variables can be scoped within loop
            if (b) continue;                 // if conditional expression omitted evaluates to true
            break;
         }

         string[] a = { "a", "b", "c" };
         foreach (string s in a) {           // foreach loop - iterate through indexers
            j = j + 1;
         }

         switch (i) {                        // switch case - expression type must be integral or string constant
            case 0:
               j = 1;
               break;
            case 1:
               j = 2;
               goto case 1;
            default:
               j = 3;
               break;
         }

         i = i - 1;
         if (b) {
            goto Label;                      // goto
         }
Label:                                       // label for goto

         return(true);                       // exit function with return value
      }

      /*********************************************************************
       *                                                                   *
       * Preprocessor Directives:                                          *
       *                                                                   *
       *********************************************************************/
      #region My Region For Demo Prepreprocessor Directives
      /// <summary>
      /// Just messing about with the region directive
      /// </summary>
         private void Preprocessor() {
            #if DEBUG
               #warning Custom Warning
               #error Custom Error
               #line 123
               System.Console.WriteLine("Debug");
            #elif TEST
               System.Console.WriteLine("Testing");
            #else
               System.Console.WriteLine("!Debug");
            #endif
         }
      #endregion

      /*********************************************************************
       *                                                                   *
       * Methods:                                                          *
       *                                                                   *
       *********************************************************************/
      private void Functions() {
         int i = Factorial(5);
         int a = 0;
         int b = 0;
         int c;
         int d = Parms(a, ref b, out c);
         i = Max(5, 3);
         double x = Max(5.0, 3.0);
         VarArgs(1,2,3);
      }

      private int Factorial(int n) {         // methods must always specify a return value (can be void)
         if (n == 1) {
            return (1);
         } else {
            return (n * Factorial(n-1));
         }
      }

      static int SFactorial(int n) {         // static methods belong to class - can be called with no instance
         if (n == 1) {
            return (1);                      // static methods are implicitly final - no override allowed
         } else {
            return (n * SFactorial(n-1));
         }
      }

      private int Parms(int x, ref int y, out int z) {
         x = 1;                              // x = by value
         y = 2;                              // y = by reference
         z = 3;                              // z = output only
         return 4;
      }

      private void VarArgs(params int[] x) { // params keyword allows var arg type calls  VarArgs(1,2,3);
      }

      /*********************************************************************
       *                                                                   *
       * Method Overloading:                                               *
       *                                                                   *
       *********************************************************************/
      private int Max(int a, int b) {        // method overloading is resolved at compile time
         if (a >= b) {                       // method of derived class always overrides - no matter how accessed
            return a;                        // all function parameters are passed by value
         } else {
            return b;
         }
      }

      private double Max(double a, double b) {
         if (a >= b) {
            return a;
         } else {
            return b;
         }
      }

      /*********************************************************************
       *                                                                   *
       * Operator Overloading:                                             *
       *                                                                   *
       *********************************************************************/
      class Rational {
         private int numer;
         private int denom;
         public static int gcd(int a, int b) {
            if (b==0) return a;
            return gcd(b, a%b);
         }
         public Rational(int n, int d) {
            int g = gcd(n, d);
            this.numer = n / g;
            this.denom = d / g;
         }
         public static implicit operator Rational(int anInt) {       // implicit conversion from int to Rational
            return new Rational(anInt, 1);
         }
         public static explicit operator int(Rational aRational) {   // explicit conversion from Rational to int
            return aRational.numer / aRational.denom;
         }
         public static bool operator==(Rational lhs, Rational rhs) {
            return ((lhs.numer * rhs.denom) == (lhs.denom * rhs.numer));
         }
         public static bool operator!=(Rational lhs, Rational rhs) {
            return !(lhs == rhs);
         }
         public static bool operator<(Rational lhs, Rational rhs) {
            return ((lhs.numer / (double)lhs.denom) < (rhs.numer / (double)rhs.denom));
         }
         public static bool operator<=(Rational lhs, Rational rhs) {
            return ((lhs < rhs) || (lhs == rhs));
         }
         public static bool operator>(Rational lhs, Rational rhs) {
            return !(lhs <= rhs);
         }
         public static bool operator>=(Rational lhs, Rational rhs) {
            return !(lhs < rhs);
         }
         public override bool Equals(object o) {
            if (!(o is Rational)) return false;
            return (this == (Rational)o);
         }
         public override int GetHashCode() {
            return (numer / (double)denom).GetHashCode();
         }
         public override string ToString() {
            return (numer.ToString() + "/" + denom.ToString());
         }
         public static Rational operator+(Rational lhs, Rational rhs) {
            int n = (lhs.numer * rhs.denom) + (rhs.numer * lhs.denom);
            int d = (lhs.denom * rhs.denom);
            int g = gcd(n, d);
            return new Rational(n / g, d / g);
         }
         public static Rational operator-(Rational lhs, Rational rhs) {
            int n = (lhs.numer * rhs.denom) - (rhs.numer * lhs.denom);
            int d = (lhs.denom * rhs.denom);
            int g = gcd(n, d);
            return new Rational(n / g, d / g);
         }
         public static Rational operator*(Rational lhs, Rational rhs) {
            int n = (lhs.numer * rhs.numer);
            int d = (lhs.denom * rhs.denom);
            int g = gcd(n, d);
            return new Rational(n / g, d / g);
         }
         public static Rational operator/(Rational lhs, Rational rhs) {
            int n = (lhs.numer * rhs.denom);
            int d = (lhs.denom * rhs.numer);
            int g = gcd(n, d);
            return new Rational(n / g, d / g);
         }
      }

      /*********************************************************************
       *                                                                   *
       * Object Methods:                                                   *
       *       Equals          GetType      MemberwiseClone    ToString    *
       *       GetHashCode     Finalize     ReferenceEquals                *
       *                                                                   *
       *********************************************************************/
      private void Objects() {
         Object x = new Rational(1,2);
         Object y = new Rational(1,2);
         bool b = x.Equals(y);
      }

      /*********************************************************************
       *                                                                   *
       * String Methods:                                                   *
       *       Chars           Empty          LastIndexOf      ToCharArray *
       *       Clone           EndsWith       Length           ToLower     *
       *       Compare         Equals         PadLeft          ToUpper     *
       *       CompareOrdinal  Format         ParRight         Trim        *
       *       CompareTo       Insert         Remove           TrimEnd     *
       *       Concat          Intern         Split            TrimStart   *
       *       Copy            IsInterned     StartsWith                   *
       *       CopyTo          Join           Substring                    *
       *                                                                   *
       *********************************************************************/
      private void Strings() {
         string a = "Hello World";
         string b = @"\Hello World";        // literal string - no escape
         int i = string.Compare(a, b);
         i = string.Compare(a, b, true);     // case insensitive
         string s = string.Concat(a, b);
         s = string.Copy(a);
         i = a.Length;
         char c = a[2];
         bool f = a.EndsWith("World");
         i = a.IndexOf("World");
         i = a.LastIndexOf("o");
         s = a.Insert(5, "fred");
         s = a.Substring(5);
         s = a.Substring(0, 5);
         char[] delimiters = {' ', ',', ';'};
         string[] xs = a.Split(delimiters);
         s = String.Format("{0,5:0.0}", 1);  // {ParamIndex[,MinWidth][:FormatString]}
         System.Console.WriteLine(s);
      }

      /*********************************************************************
       *                                                                   *
       * StringBuilder Methods:                                            *
       *       Append        Chars            Length           Remove      *
       *       AppendFormat  EnsureCapacity   MaxCapacity      Replace     *
       *       Capacity      Insert                                        *
       *                                                                   *
       *********************************************************************/
      private void StringBuilders() {
         System.Text.StringBuilder s = new System.Text.StringBuilder("");
         s.Append("abc");
         s.AppendFormat("{0}{1}{2}", "d", "e", "f");
      }

      /*********************************************************************
       *                                                                   *
       * Regex Methods:                                                    *
       *                                                                   *
       *********************************************************************/
      private void RegEx() {
         string s = "One,Two,Three Liberty Associates, Inc.";
         System.Text.RegularExpressions.Regex re = new System.Text.RegularExpressions.Regex(" |, |,");
         re.Split(s);
         foreach (string a in re.Split(s)) {
            System.Console.WriteLine(a);
         }
      }

      /*********************************************************************
       *                                                                   *
       * Array Methods:                                                    *
       *       BinarySearch    GetLength      IsFixedSize      Rank        *
       *       Clear           GetLowerBound  IsReadOnly       Reverse     *
       *       Copy            GetUpperBound  IsSynchronized   SetValue    *
       *       CreateInstance  IndexOf        LastIndexOf      Sort        *
       *       GetEnumerator   Initialize     Length           SyncRoot    *
       *                                                                   *
       *********************************************************************/
      private void Arrays() {
         int i;
         int[] a;
         int[] b = new int[20];              // elements initialize to null
         int[,] c;
         int[,] d = new int[10,20];
         int[] primes = {2, 3, 5, 7, 11, 13, 17,};
         a = new int[10];
         System.Array.Copy(primes, 0, a, 0, 2);
         for (i = 0; i < a.Length; i++) a[i] = i;
         foreach (int j in a) a[j] = j;
         int[][] e = new int[10][];          // multidimensional arrays do not have to be rectangular
         for (i = 0; i < e.Length; i++) e[i] = new int[i+1];
      }

      /*********************************************************************
       *                                                                   *
       * Indexers:                                                         *
       *                                                                   *
       *********************************************************************/
      private void Indexers() {
         Indexer indx = new Indexer();
         indx.Add("a");
         indx.Add("b");
         for (int j = 0; j < indx.GetNumEntries(); j++) {
            System.Console.WriteLine(indx[j]);
         }
      }

      class Indexer {
         private string[] s = new string[256];
         private int i = 0;
         public void Add(string a) {
            s[i++] = a;
         }
         public string this[int index] {
            get {
               if ((index < 0) || (index >= s.Length)) {
                  // handle bad index
               }
               return s[index];
            }
            set {
               if (index >= i) {
                  // add only through add method
               } else {
                  s[index] = value;
               }
            }
         }
         public int GetNumEntries() {
            return i;
         }
      }

      /*********************************************************************
       *                                                                   *
       * Collection Classes:                                               *
       *                                                                   *
       *********************************************************************/
      private void Collect() {
         // ArrayList - dynamically sized array
         System.Collections.ArrayList a = new System.Collections.ArrayList();
         a.Add("Fred");
         a.Add("Hank");
         a.Sort();
         foreach (string x in a) System.Console.WriteLine(x);

         // BitArray - dynamically sized boolean array
         System.Collections.BitArray b = new System.Collections.BitArray(0);
         b.Length = 2;
         b[1] = true;
         b.Xor(b);

         // HashTable - dictionary
         System.Collections.Hashtable d = new System.Collections.Hashtable();
         d["ab"] = 1;
         d["cd"] = 2;
         int i = (int)d["ab"];

         // SortedList - sorted dictionary
         System.Collections.Hashtable e = new System.Collections.Hashtable();
         e["ab"] = 1;
         e["cd"] = 2;
         i = (int)e["ab"];

         // Queue - fifo
         System.Collections.Queue q = new System.Collections.Queue();
         q.Enqueue(1);
         q.Enqueue(2);
         i = (int)q.Dequeue();
         i = (int)q.Dequeue();

         // Stack - lifo
         System.Collections.Stack s = new System.Collections.Stack();
         s.Push(1);
         s.Push(2);
         i = (int)s.Pop();
         i = (int)s.Pop();

         // StringCollection
         System.Collections.Specialized.StringCollection c = new System.Collections.Specialized.StringCollection();
         c.Add("abc");
         c.Add("def");
      }

      /*********************************************************************
       *                                                                   *
       * Exceptions:                                                       *
       *                                                                   *
       *********************************************************************/
      private void Exceptions(){
         int i = 10;
         int[] a = new int[10];

         try {
            a[i] = i;
         } catch (IndexOutOfRangeException e) {
            //System.Console.WriteLine(e.ToString());
         } catch (Exception e) {             // catch order should be from lowest subclass to highest superclass
            //System.Console.WriteLine(e.ToString());
            throw e;                         // exception can be rethrown - pass it up to calling method
         } catch {                           // default exception handler
            //System.Console.WriteLine(e.ToString());
            throw;
         } finally {                         // this block will always be executed even when no exception
         }

         try {                               // C# does not use checked exceptions
            throw new ChrisException("User Defined Exception");
         } catch (ChrisException e) {
            //System.Console.WriteLine(e.ToString());
         } catch (Exception e) {
            //System.Console.WriteLine(e.ToString());
         }

         try {                               // can also be used to perform operations if return executed
            return;
         } finally {                         // break/continue/return/throw statement will cause forget of branch
         }
      }

      // user defined exception
       public class ChrisException : System.Exception {
          public ChrisException() : this("") {
          }
          public ChrisException(String s) : base(s) {
          }
       }

      /*********************************************************************
       *                                                                   *
       * Pointers:                                                         *
       *                                                                   *
       *********************************************************************/
      struct Coordinate {
         public int x;
         public int y;
         public Coordinate(int x, int y) {
            this.x = x;
            this.y = y;
         }
      }

      void Pointers() {
         int i = 5;
         Coordinate xy = new Coordinate(10, 20);
         /*
         unsafe {
            int* p = &i;
            *p = 12356;
            Coordinate* pxy = &xy;
            (*pxy).x = (*pxy).x + 100;
            pxy->y = pxy->y + 100;
         }
         */
      }

      /*********************************************************************
       *                                                                   *
       * Delegates:                                                        *
       *                                                                   *
       *********************************************************************/
      delegate void MethodRefs(string s);
      event MethodRefs Print;

      void PrintString(string s) { System.Console.WriteLine(s); }

      void Delegates() {
         MethodRefs mdg = new MethodRefs(PrintString);
         mdg += new MethodRefs(PrintString);
         mdg("Delegate Hello");
         mdg("Delegate World");
         Print += mdg;
         Print("Easy as pie.");
      }

      /*********************************************************************
       *                                                                   *
       * IO:                                                               *
       *                                                                   *
       *********************************************************************/
      void FileIO() {
         System.IO.Stream ios = new System.IO.FileStream("foo.txt", System.IO.FileMode.Create);
         ios.WriteByte(67);
         ios.WriteByte(35);
         ios.WriteByte(0xd);
         ios.WriteByte(0xa);
         ios.Close();

         ios = new System.IO.FileStream("foo.txt", System.IO.FileMode.Open);
         int i = ios.ReadByte();
         i = ios.ReadByte();
         ios.Close();

         ios = new System.IO.FileStream("bar.txt", System.IO.FileMode.Create);
         System.IO.StreamWriter sw = new System.IO.StreamWriter(ios, System.Text.Encoding.ASCII);
         sw.WriteLine("C#");
         sw.Close();

         ios = new System.IO.FileStream("bar.txt", System.IO.FileMode.Open);
         System.IO.StreamReader sr = new System.IO.StreamReader(ios, System.Text.Encoding.ASCII);
         string a = sr.ReadLine();
         sr.Close();
      }

      /*********************************************************************
       *                                                                   *
       * Threading:                                                        *
       *                                                                   *
       *********************************************************************/
      void Threads() {
         System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(StartMe));
         t.Start();
      }

      void StartMe() {
         lock(this) {
            //System.Threading.Monitor.Wait(this);
            //System.Threading.Monitor.Pulse(this);
            System.Console.WriteLine("Thread Me");
         }
      }

      /************************************************************************
       *                                                                      *
       * Attributes:                                                          *
       *                                                                      *
       ************************************************************************/
      [AttributeUsage(AttributeTargets.Class |
          AttributeTargets.Constructor |
          AttributeTargets.Field |
          AttributeTargets.Method |
          AttributeTargets.Property,
          AllowMultiple = true)]
      public class MyAttribute : System.Attribute {
         private int commentID;
         private string comment;
         public MyAttribute(int commentID, string comment) {
            this.commentID = commentID;
            this.comment = comment;
         }
         public int CommentID {
            get { return commentID; }
         }
         public string Comment {
            get { return comment; }
            set { comment = value; }
         }
      }

      // using attributes
      [MyAttribute(1, "Hello World")]
      [MyAttribute(2, "Foo Bar")]
      class TestAttributes { }

      /*********************************************************************
       *                                                                   *
       * Reflection:                                                       *
       *                                                                   *
       *********************************************************************/
      void DumpType(System.Type t) {
         System.Console.WriteLine("Type: {0}", t);
         System.Reflection.MemberInfo[] a = t.GetMembers();
         foreach (System.Reflection.MemberInfo m in a) {
            Console.WriteLine("  {0} = {1}", m.MemberType, m);
         }
         // filtering for a method
         a = t.FindMembers(
            System.Reflection.MemberTypes.Method,
            System.Reflection.BindingFlags.Public |
               System.Reflection.BindingFlags.Static |
               System.Reflection.BindingFlags.NonPublic |
               System.Reflection.BindingFlags.Instance |
               System.Reflection.BindingFlags.DeclaredOnly,
            Type.FilterName, "Get*");
         foreach (System.Reflection.MemberInfo m in a) {
            Console.WriteLine("  {0} = {1}", m.MemberType, m);
         }
      }
      void Reflections() {
         // type discovery
         System.Type ta = System.Type.GetType("System.Int32");
         System.Type tb = typeof(System.Int32);
         DumpType((new System.Object()).GetType());
         //DumpType(typeof(string));

         // viewing attribute metadata
         System.Reflection.MemberInfo inf = typeof(TestAttributes);
         object[] a = inf.GetCustomAttributes(typeof(MyAttribute), false);
         foreach (object m in a) {
            MyAttribute x = (MyAttribute)m;
            System.Console.WriteLine(x.CommentID + " : " + x.Comment);
         }
      }

      /*********************************************************************
       *                                                                   *
       * Database:                                                         *
       *                                                                   *
       *********************************************************************/
      void Databases() {
         System.Data.SqlClient.SqlConnection Db;
         System.Data.SqlClient.SqlDataAdapter Da;
         System.Data.DataSet Ds;
         System.Data.DataTable Dt;
         System.Data.SqlClient.SqlCommand Cmd;
         System.Data.SqlClient.SqlDataReader Rs;

         string connectionStr = "Server=.; Database=Northwind; Integrated Security=sspi";
         string commandStr;

         // open up a database connection
         Db = new System.Data.SqlClient.SqlConnection(connectionStr);
         Db.Open();

         // create a table
         commandStr = "CREATE TABLE TestCSharp(" +
                      "   TestCD      CHAR(2)     NOT NULL PRIMARY KEY," +
                      "   Description VARCHAR(80) NOT NULL)";
         Cmd = new System.Data.SqlClient.SqlCommand(commandStr, Db);
         Cmd.CommandType = System.Data.CommandType.Text;
         Rs = Cmd.ExecuteReader();
         Rs.Close();

         // create a stored procedure for saves
         commandStr = "CREATE PROCEDURE spSaveTestCSharp" +
                      "   @TestCD CHAR(2) = NULL," +
                      "   @Description VARCHAR(80) = NULL" +
                      "   AS" +
                      "   SET NOCOUNT ON" +
                      "   INSERT INTO TestCSharp(TestCD, Description) VALUES(@TestCD, @Description)" +
                      "   SELECT" +
                      "      Status = 0," +
                      "      Token  = '1234'";
         Cmd = new System.Data.SqlClient.SqlCommand(commandStr, Db);
         Cmd.CommandType = System.Data.CommandType.Text;
         Rs = Cmd.ExecuteReader();
         Rs.Close();

         // create a stored procedure for reads
         commandStr = "CREATE PROCEDURE spReadTestCSharp" +
                      "   AS" +
                      "   SET NOCOUNT ON" +
                      "   SELECT" +
                      "      Status      = 0," +
                      "      Token       = '1234'," +
                      "      TestCD      = tab.TestCD," +
                      "      Description = tab.Description" +
                      "   FROM TestCSharp tab" +
                      "   ORDER BY tab.TestCD";
         Cmd = new System.Data.SqlClient.SqlCommand(commandStr, Db);
         Cmd.CommandType = System.Data.CommandType.Text;
         Rs = Cmd.ExecuteReader();
         Rs.Close();

         // insert via stored procedure call
         Cmd = new System.Data.SqlClient.SqlCommand("spSaveTestCSharp", Db);
         Cmd.CommandType = System.Data.CommandType.StoredProcedure;
         Cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@TestCD", System.Data.SqlDbType.VarChar, 2));
         Cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@Description", System.Data.SqlDbType.VarChar, 80));
         Cmd.Parameters["@TestCD"].Value = "TX";
         Cmd.Parameters["@Description"].Value = "Texas";
         Rs = Cmd.ExecuteReader();
         Rs.Read();
         int Status = (int)Rs["Status"];
         string Token = (string)Rs["Token"];
         if (Status != 0) {
            System.Console.WriteLine("Error in test insert");
         }
         Rs.Close();

         // read via stored procedure call
         Cmd = new System.Data.SqlClient.SqlCommand("spReadTestCSharp", Db);
         Cmd.CommandType = System.Data.CommandType.StoredProcedure;
         Rs = Cmd.ExecuteReader();
         Rs.Read();
         Status = (int)Rs["Status"];
         Token = (string)Rs["Token"];
         if (Status != 0) {
            System.Console.WriteLine("Error in test insert");
         } else {
            do
               System.Console.WriteLine(Rs["TestCD"] + " " + Rs["Description"]);
            while (Rs.Read());
         }
         Rs.Close();

         // example using DataAdapter (sans SqlConnection)
         commandStr = "SELECT * FROM TestCSharp";
         Da = new System.Data.SqlClient.SqlDataAdapter(commandStr, connectionStr);
         Ds = new System.Data.DataSet();
         Da.Fill(Ds, "Test");
         Dt = Ds.Tables[0];
         foreach (System.Data.DataRow row in Dt.Rows) {
            System.Console.WriteLine(row["TestCD"] + " " + row["Description"]);
         }

         // drop the read stored procedure
         commandStr = "DROP PROCEDURE spReadTestCSharp";
         Cmd = new System.Data.SqlClient.SqlCommand(commandStr, Db);
         Cmd.CommandType = System.Data.CommandType.Text;
         Rs = Cmd.ExecuteReader();
         Rs.Close();

         // drop the save stored procedure
         commandStr = "DROP PROCEDURE spSaveTestCSharp";
         Cmd = new System.Data.SqlClient.SqlCommand(commandStr, Db);
         Cmd.CommandType = System.Data.CommandType.Text;
         Rs = Cmd.ExecuteReader();
         Rs.Close();

         // drop the table
         commandStr = "DROP TABLE TestCSharp";
         Cmd = new System.Data.SqlClient.SqlCommand(commandStr, Db);
         Cmd.CommandType = System.Data.CommandType.Text;
         Rs = Cmd.ExecuteReader();
         Rs.Close();

         // close the database connection
         Db.Close();
      }

      /*********************************************************************
       *                                                                   *
       * Networking:                                                       *
       *                                                                   *
       *********************************************************************/
      void Networking() {
         System.Net.WebClient wc = new System.Net.WebClient();
         System.Text.UTF8Encoding utf = new System.Text.UTF8Encoding();
         try {
            // can't seem to get this thing to work???
            string doc = utf.GetString(wc.DownloadData("http://localhost/"));
            System.Console.WriteLine(doc);
         } catch (System.Net.WebException e) {
            Console.WriteLine(e);
         }
      }

      /*********************************************************************
       *                                                                   *
       * Inner Classes:                                                    *
       *                                                                   *
       *********************************************************************/
      public class InnerClass {              // C# inner classes are equivalent to static inner classes in Java
         int a;                              // No C# equivalent for instance inner classes or anonymous classes
         public int b;                       // can not access instance methods or properties of the outer class
         private int c;

         public InnerClass() {
            InnerInnerClass xa = new InnerInnerClass();
         }

         public class InnerInnerClass {
            int a;
            public int b;
            private int c;

            public InnerInnerClass() {
               System.Console.WriteLine("InnerInnerClass");
               a = 0;
            }
         }
      }
   }

   /************************************************************************
    *                                                                      *
    * Outer Classes:                                                       *
    *                                                                      *
    ************************************************************************/
   class OuterClass {                        // outer class can not be declared public
      const double PI = 3.14;
      static int objcount = 0;

      internal OuterClass() {
         int i;
         double x;
         String s;

         XShape x1;
         XShape x2;
         XShape x3;
         XShape x4;
         XShape x5;
         XRectangle xa;
         IConvert xb;

         x1 = new XRectangle(3.0, 4.0);
         x2 = new Square(3.0);
         x3 = new Triangle(1.0, 2.0, 3.0);
         x4 = new Circle(4.0);
         x5 = new EquilateralTriangle(5.0);

         xa = (XRectangle)x2;                // polymorphism - base class object can point to any derived class
         x2 = xa;                            // assigning object to super class does not require casting

         x = x1.Area();                      // appropriate method for the subclass instance is called
         i = x2.Sides;                       // superclass variables can only access variables and methods
         s = x3.ToString();                  //    that exist at the superclass level of the variable

         xb = (IConvert)x4;                  // polymorphism - interface var can point to any class that implements
         x = xb.InchToMM();

         System.Console.WriteLine(x1.ToString() + ":" + x2.ToString() + ":" + x3.ToString() + ":" +
           x4.ToString() + ":" + x5.ToString());
      }

      // inner class objects outside of class can be created only in context of the top level class
      OuterClass(String s) {
         Syntax xa = new Syntax();
         Syntax.InnerClass xb = new Syntax.InnerClass();
         Syntax.InnerClass.InnerInnerClass xc = new Syntax.InnerClass.InnerInnerClass();
      }
   }

   /************************************************************************
    *                                                                      *
    * SubClasses:                                                          *
    *                                                                      *
    ************************************************************************/
   abstract class XShape {                   // abstract class can not be alocated - serves as subclass template
      internal String name;
      internal int Sides = 0;                // subclasses inherit all fields and methods not defined as private

      internal XShape(int Sides) {
         this.Sides = Sides;
      }

      internal abstract double Area();       // abstract requires all subclasses to define this method

      internal virtual double Perimeter() {  // virtual methods are intended to be overridden - must be explicit (final is default)
         return 0;
      }

      public override String ToString() {    // override the inherited Object method
         return name;
      }
   }

   class XRectangle : XShape {               // extends identifies this as a subclass of the specified superclass
      internal double length = 1.0;          // subclass inherits all members of superclass that are not private
      double width = 1.0;

      internal XRectangle(double length, double width) :  base(4) {  // constructors of base class not inherited - but can be called
         name = "XRectangle";
         this.length = length;
         this.width = width;
      }

      internal XRectangle() : this(2, 4) {   // this or super constructor must be first statement in constructor
      }

      override internal double Area() {      // define abstract method
         return length * width;
      }

      override internal double Perimeter() {
         return 2 * length * width;
      }
   }

   sealed class Square : XRectangle {        // sealed (final) class prevents any further subclassing
      new internal double length;            // new keyword indicates intentionally shadowing

      internal Square(double length) : base(length, length) {
         name = "Square";
         this.length = length;
         base.length = length;               // accessing shadowed variables allowed through super
         ((XRectangle)this).length = length; // accessing shadowed variables allowed through casting
         double x = base.Area();             // accessing overridden method allowed through super
         x = ((XRectangle)this).Area();      // casting does not provide access to the overridden method
      }

      override internal double Area() {      // override base class method - Perimeter function is inherited
         return base.Area();                 // overriding method cannot be less accessible than overridden method
      }                                      // throws clause of overriding method must match overridden method
   }

   class Triangle : XShape {
      internal double[] side = new double[3];
      double xbase;
      double height;

      internal Triangle(double a, double b, double c) : base(3) {
         name = "Triangle";
         side[0] = a;
         side[1] = b;
         side[2] = c;
         xbase = a;
         height = 1.0;
      }

      override internal double Area() {
         return 0.5 * xbase * height;
      }

      override internal double Perimeter() {
         return (side[0] + side[1] + side[2]);
      }
   }

   class Factors {
      public const double PI = 3.14;
      public static double PISQUARE = Math.Pow(PI, 2);
      public const double INCH_TO_MM = 25.4;
      private Factors() { }
   }

   /************************************************************************
    *                                                                      *
    * Interfaces:                                                          *
    *                                                                      *
    ************************************************************************/
   interface IConvert {                      // an interface is a collection of abstract methods
      double InchToMM();                     // methods in interface are always abstract and public (can not specify access modifier)
   }                                         // C# does not support constant fields in interfaces

   interface IMoreConvert : IConvert {       // interfaces can be extended similar to classes
      double MMToInch();
   }

   class Circle : XShape, IMoreConvert {     // multiple interfaces may be implemented
      double radius;                         // explicit implementation can be used for methods that exist in more than one interface
                                             // IMoreConvert.MMToInch() - can only be accessed through cast of the object to interface
      internal Circle(double radius) : base(0) {
         name = "Circle";
         this.radius = radius;
      }

      override internal double Area() {      // abstract methods required from superclass
         return Factors.PI * Factors.PI * radius;
      }

      override internal double Perimeter() { // override superclass method
         return 2 * Factors.PI * radius;
      }

      public double InchToMM() {             // abstract method for interface
         return (Perimeter() * Factors.INCH_TO_MM);
      }

      public double MMToInch() {
         return radius * (1 / Factors.INCH_TO_MM);
      }
   }

   internal class EquilateralTriangle : Triangle, IConvert {
      internal EquilateralTriangle(double a) : base(a, a, a) {
         name = "EquilateralTriangle";
      }

      override internal double Area() {
         return 0.5;
      }

      public double InchToMM() {             // abstract method for interface
         return 3 * side[0] * Factors.INCH_TO_MM;
      }
   }

   /************************************************************************
    *                                                                      *
    * Structs:                                                             *
    *                                                                      *
    ************************************************************************/
   public struct Location {                  // structs do not support inheritance (can implement interfaces)
      private int xval;                      // initialization not supported
      private int yval;
      public Location(int x, int y) {        // structs are value objects
         xval = x;                           // destructors not supported
         yval = y;
      }
      public int x {
         get {
            return xval;
         }
         set {
            xval = value;
         }
      }
      public int y {
         get {
            return yval;
         }
         set {
            yval = value;
         }
      }
      public override string ToString() {
         return String.Format("{0}, {1}", xval, yval);
      }
   }

   /************************************************************************
    *                                                                      *
    * Link Lists:                                                          *
    *                                                                      *
    ************************************************************************/
   class LinkList {
      LinkList prev;
      LinkList next;

      LinkList() {
         prev = null;
         next = null;
      }

      LinkList(LinkList x) {
         x.prev = x;
         x.next = null;
         x.prev.next = this;
      }
   }
}



Chris Rathman / Chris.Rathman@tx.rr.com