Code Listings

Chapter 2: C# Language Basics

A first C# program:

using System;                     // importing namespace

class Test                        // class declaration
{                      
  static void Main ()             //   method declaration
  {
    int x = 12 * 30;              //     statement 1
    Console.WriteLine (x);        //     statement 2
  }                               //   end of method
}                                 // end of class

Refactoring with a method:

using System;

class Test
{
  static void Main ()
  {
    Console.WriteLine (FeetToInches (30));      // 360
    Console.WriteLine (FeetToInches (100));     // 1200
  }

  static int FeetToInches (int feet)
  {
    int inches = feet * 12;
    return inches;
  }
}

Syntax example program:

using System;

class Test
{
  static void Main ()
  {
    int x = 12 * 30;
    Console.WriteLine (x);
  }
}

Custom types:

using System;

public class UnitConverter
{                       
  int ratio;                                                 // field
  public UnitConverter (int unitRatio) {ratio = unitRatio; } // constructor
  public int Convert   (int unit)    {return unit * ratio; } // method
}                                           

class Test 
{
  static void Main ()
  {
    UnitConverter feetToInchesConverter = new UnitConverter(12);
    UnitConverter milesToFeetConverter  = new UnitConverter(5280);

    Console.WriteLine (feetToInchesConverter.Convert(30));    // 360
    Console.WriteLine (feetToInchesConverter.Convert(100));   // 1200
    Console.WriteLine (feetToInchesConverter.Convert(
                         milesToFeetConverter.Convert(1)));   // 63360               
  }
}

Instance vs. Static Members:

using System;

public class Panda
{
  public string Name;             // instance field
  public static int Population;   // static field    

  public Panda (string n)         // constructor
  {
    Name = n;                     // assign the instance field
    Population = Population + 1;  // increment the static Population field
  } 
}

class Test
{
  static void Main()
  {
    Panda p1 = new Panda ("Pan Dee");      // create new Panda instance
    Panda p2 = new Panda ("Pan Dah");      // create new Panda instance
    Console.WriteLine (p1.Name);           // access instance field
    Console.WriteLine (p2.Name);           // access instance field
    Console.WriteLine (Panda.Population);  // access static field
  }
}

Conversions:

int x = 123456;      // int is a 32-bit integer
long y = x;          // implicit conversion to 64-bit integer
short z = (short)x;   // explicit conversion to 16-bit integer

Value Types vs. Reference Types:

static void Main ()
{
  Point p1 = new Point();
  p1.X = 7;

  Point p2 = p1;             // assignment causes copy

  Console.WriteLine (p1.X);  // 7
  Console.WriteLine (p2.X);  // 7

  p1.X = 9;                  // change p1.X

  Console.WriteLine (p1.X);  // 9
  Console.WriteLine (p2.X);  // 7
}
static void Main ()
{
  Point p1 = new Point();
  p1.X = 7;

  Point p2 = p1;             // copies p1 reference

  Console.WriteLine (p1.X);  // 7
  Console.WriteLine (p2.X);  // 7

  p1.X = 9;                  // change p1.X

  Console.WriteLine (p1.X);  // 9
  Console.WriteLine (p2.X);  // 9
}

Numeric literals:

Console.WriteLine (        1.0.GetType());  // Double  (double)
Console.WriteLine (       1E06.GetType());  // Double  (double)
Console.WriteLine (          1.GetType());  // Int32   (int)
Console.WriteLine ( 0xF0000000.GetType());  // UInt32  (uint)

checked operator:

int a = 1000000;
int b = 1000000;
 
// Check an expression
int c = checked (a*b);
 
// Check every expression in a statement block
checked
{
   // ...
   c = a * b;
   // ...
}
int x = int.MaxValue;
int y = unchecked (x + 1);
unchecked { int z = x + 1; }
int x = int.MaxValue + 1;               // Compile-time error
int y = unchecked (int.MaxValue + 1);   // No errors

Special float and double values:

Console.WriteLine ( 1.0 /  0.0);                  //  Infinity
Console.WriteLine (-1.0 /  0.0);                  // -Infinity
Console.WriteLine ( 1.0 / -0.0);                  // -Infinity
Console.WriteLine (-1.0 / -0.0);                  //  Infinity
Console.WriteLine ( 0.0 /  0.0);                  //  NaN
Console.WriteLine ((1.0 /  0.0) - (1.0 / 0.0));   //  NaN
Console.WriteLine (0.0 / 0.0 == double.NaN);   // False
Console.WriteLine (double.IsNaN(0.0 / 0.0));   // True

Real number rounding errors:

float tenth = 0.1f;                       // Not quite 0.1
float one   = 1f;
Console.WriteLine (one - tenth * 10f);    // -1.490116E-08
decimal m = 1M / 6M;               // 0.1666666666666666666666666667M
double  d = 1.0 / 6.0;             // 0.16666666666666666

decimal notQuiteWholeM = m+m+m+m+m+m;  // 1.0000000000000000000000000002M
double  notQuiteWholeD = d+d+d+d+d+d;  // 0.99999999999999989

Console.WriteLine (notQuiteWholeM == 1M);   // False
Console.WriteLine (notQuiteWholeD < 1.0);   // True

Equality and comparison pperators:

public class Dude
{
  public string Name;
  public Dude (string n) { Name = n; }
}

Dude d1 = new Dude ("John");
Dude d2 = new Dude ("John");
Console.WriteLine (d1 == d2);       // False
Dude d3 = d1;  
Console.WriteLine (d1 == d3);       // True

Conditional operators:

static bool UseUmbrella (bool rainy, bool sunny, bool windy)
{
  return ! windy && (rainy || sunny);
}
static int Max (int a, int b)
{
  return (a > b) ? a : b; 
}

Arrays:

char[] vowels = new char[5];    // Declare an array of 5 characters

vowels [0] = 'a';
vowels [1] = 'e';
vowels [2] = 'i';
vowels [3] = 'o';
vowels [4] = 'u';
Console.WriteLine (vowels [1]);      // e

for (int i = 0; i < vowels.Length; i++)
  Console.Write (vowels [i]);            // aeiou
char[] vowels = new char[] {'a','e','i','o','u'};

Multidimensional arrays, rectangular:

int [,] matrix = new int [3, 3];

for (int i = 0; i < matrix.GetLength(0); i++)
  for (int j = 0; j < matrix.GetLength(1); j++)
    matrix[i, j] = i * 3 + j;
int[,] matrix = new int[,]
{
  {0,1,2},
  {3,4,5},
  {6,7,8}
};

Multidimensional arrays, jagged:

int [][] matrix = new int [3][];

for (int i = 0; i < matrix.Length; i++)
{
  matrix[i] = new int [3];                    // create inner array
  for (int j = 0; j < matrix[i].Length; j++)
    matrix[i][j] = i * 3 + j;
}
int[][] matrix = new int[][]
{
  new int[] {0,1,2},
  new int[] {3,4,5},
  new int[] {6,7,8}
};

Simplified array initialization expressions:

char[] vowels = {'a','e','i','o','u'};

int[,]rectangularMatrix =
{
  {0,1,2},
  {3,4,5},
  {6,7,8}
};

int[][]jaggedMatrix =
{
  new int[] {0,1,2},
  new int[] {3,4,5},
  new int[] {6,7,8}
};
var i = 3;           // i is implicitly of type int
var s = "sausage";   // s is implicitly of type string

// Therefore:

var rectMatrix = new int[,]    // rectMatrix is implicitly of type int[,]
{
  {0,1,2},
  {3,4,5},
  {6,7,8}
};

var jaggedMat = new int[][]    // jaggedMat is implicitly of type int[][]
{
  new int[] {0,1,2},
  new int[] {3,4,5},
  new int[] {6,7,8}
};

Stack and Heap:

using System;
using System.Text;

class Test
{
  static void Main ()
  {
    StringBuilder ref1 = new StringBuilder("object1");
    StringBuilder ref2 = new StringBuilder("object2");
    StringBuilder ref3 = ref2;
    ref1 = ref2 = null;                           
    Console.WriteLine(ref3);                   // object2
  }  
}

Passing arguments by value:

class Test 
{
  static void Foo(int p)
  {
    p = p + 1;              // increment p by 1
    Console.WriteLine(p);   // write p to screen
  }

  static void Main()
  {
    int x = 8;
    Foo(x);                // make a copy of x
    Console.WriteLine(x);  // x will still be 8
  }
}
class Test 
{
  static void Foo (StringBuilder fooSB)
  {
    fooSB.Append ("test");
    fooSB = null;
  }

  static void Main()
  {
    StringBuilder sb = new StringBuilder();
    Foo (sb);
    Console.WriteLine (sb.ToString());    // test
  }
}

Passing arguments by reference:

class Test
{
  static void Foo (ref int p)
  {
    p = p + 1;              // increment p by 1
    Console.WriteLine(p);   // write p to screen
  }

  static void Main ()
  {
    int x = 8;
    Foo (ref x);            // Ask Foo to deal directly with x
    Console.WriteLine(x);   // x is now 9
  }
}
using System;

class Test
{
  static void Swap (ref string a, ref string b)
  {
    string temp = a;
    a = b;
    b = temp;
  }

  static void Main ()
  {
    string x = "Penn";
    string y = "Teller";
    Swap (ref x, ref y);
    Console.WriteLine (x);   // Teller
    Console.WriteLine (y);   // Penn
  }
}

The out modifier:

using System;

class Test
{
  static void Split (string name, out string firstNames, 
                     out string lastName)
  {
     int i = name.LastIndexOf(' ');
     firstNames = name.Substring (0, i);
     lastName   = name.Substring (i + 1);
  }

  static void Main()
  {
    string a, b;
    Split ("Stevie Ray Vaughn", out a, out b);
    Console.WriteLine (a);                      // Stevie Ray
    Console.WriteLine (b);                      // Vaughn
  }
}

Implications of passing by reference:

using System;

class Test
{
  static int x;

  static void Main() { Foo(out x); }

  static void Foo(out int y)
  {
    Console.WriteLine (x);                // x is 0
    y = 1;                                // mutate y
    Console.WriteLine (x);                // x is 1
  }
}

The params modifier:

using System;

class Test
{
  static int Sum (params int[] ints)
  {
    int sum = 0;
    for (int i = 0; i < ints.Length; i++)
      sum += ints[i];                       // increase sum by ints[i]
    return sum;
  }

  static void Main()
  {
    int total = Sum (1, 2, 3, 4);
    Console.WriteLine(total);              // 10
  }
}

var: implicity typed local variables:

var x = 5;
var y = "hello";
var z = new System.Text.StringBuilder();
var req = (System.Net.FtpWebRequest) System.Net.WebRequest.Create ("...");

The switch statement:

static void ShowCard(int cardNumber)
{
  switch(cardNumber)
  {
    case 13:
      Console.WriteLine("King");
      break;
    case 12:
      Console.WriteLine("Queen");
      break;
    case 11:
      Console.WriteLine("Jack");
      break;
    case -1:                         // joker is -1
      goto case 12;                  // in this game joker counts as queen
    default:                         // executes for any other cardNumber
      Console.WriteLine(cardNumber);
      break;
  }
}

Listing common cases sequentially:

switch (cardNumber)
{
  case 13:
  case 12:
  case 11:
    Console.WriteLine ("Face card");
    break;
  default:
    Console.WriteLine ("Plain card");
    break;
}

break and continue:

int x = 0;
while (true)
{
  if (x++ > 5)
    break;      // break from the loop
}
for (int i = 0; i < 4; i++)
{
  if ((i % 2) == 0)       // true if i is even
    continue;             // continue with next iteration
  Console.WriteLine (i);
}

goto:

int i = 0;
startLoop:
if (i < 3 )
{
  Console.WriteLine(i);
  i++;
  goto startLoop;
}

Advanced namespace features: extern

// csc target:library /out:Widgets1.dll widgetsv1.cs

namespace Widgets
{
  public class Widget {}
}
// csc target:library /out:Widgets2.dll widgetsv2.cs

namespace Widgets
{
  public class Widget {}
}
// csc /r:W1=Widgets1.dll /r:W2=Widgets2.dll application.cs 

extern alias W1;
extern alias W2;

class Test
{
  static void Main()
  {
    W1.Widgets.Widget w1 = new W1.Widgets.Widget();
    W2.Widgets.Widget w2 = new W2.Widgets.Widget();
  }
}

Namespace alias qualifiers:

namespace N
{
  class A
  {
    public class B {}                   // Nested type
    static void Main() { new A.B(); }   // Instantiate class B
  }
}

namespace A
{
  class B {}
}

namespace :: token:

namespace N
{
  class A
  {
    static void Main()
    {
      System.Console.WriteLine(new A.B());
      System.Console.WriteLine(new global::A.B());
    }

    public class B {}
  }
}

namespace A
{
  class B {}
}
extern alias W1;
extern alias W2;

class Test
{
  static void Main()
 {
    W1::Widgets.Widget w1 = new W1::Widgets.Widget();
    W2::Widgets.Widget w2 = new W2::Widgets.Widget();
  }
}

 

© 2007, O'Reilly Media, Inc. All rights reserved

C# 3.0 in a Nutshell
Buy from amazon.com Available now