您的位置:首页 > Web前端

The C# Complete Reference code

2011-08-22 19:28 302 查看
listing 1

// A XML documentation example.

using System;

/** <remark>

This is an example of multiline XML documentation.

The Test class demonstrates several tags.

</remark>

*/

class Test {

/// <summary>

/// Main is where execution begins.

/// </summary>

public static void Main() {

int sum;

sum = Summation(5);

Console.WriteLine("Summation of " + 5 + " is " + sum);

}

/// <summary>

/// Summation returns the summation of its argument.

/// <param name = "val">

/// The value to be summed is passed in val.

/// </param>

/// <see cref="int"> </see>

/// <returns>

/// The summation is returned as an int value.

/// </returns>

/// </summary>

static int Summation(int val) {

int result = 0;

for(int i=1; i <= val; i++)

result += i;

return result;

}

}

listing 1

/*

This is a simple C# program.

Call this program Example.cs.

*/

using System;

class Example {

// A C# program begins with a call to Main().

public static void Main() {

Console.WriteLine("A simple C# program.");

}

}

listing 2

// This version does not include the using System statement.

class Example {

// A C# program begins with a call to Main().

public static void Main() {

// Here, Console.WriteLine is fully qualified.

System.Console.WriteLine("A simple C# program.");

}

}

listing 3

// This program demonstrates variables.

using System;

class Example2 {

public static void Main() {

int x; // this declares a variable

int y; // this declares another variable

x = 100; // this assigns 100 to x

Console.WriteLine("x contains " + x);

y = x / 2;

Console.Write("y contains x / 2: ");

Console.WriteLine(y);

}

}

listing 4

/*

This program illustrates the differences

between int and double.

*/

using System;

class Example3 {

public static void Main() {

int ivar; // this declares an int variable

double dvar; // this declares a floating-point variable

ivar = 100; // assign ivar the value 100

dvar = 100.0; // assign dvar the value 100.0

Console.WriteLine("Original value of ivar: " + ivar);

Console.WriteLine("Original value of dvar: " + dvar);

Console.WriteLine(); // print a blank line

// now, divide both by 3

ivar = ivar / 3;

dvar = dvar / 3.0;

Console.WriteLine("ivar after division: " + ivar);

Console.WriteLine("dvar after division: " + dvar);

}

}

listing 5

// Compute the area of a circle.

using System;

class Circle {

public static void Main() {

double radius;

double area;

radius = 10.0;

area = radius * radius * 3.1416;

Console.WriteLine("Area is " + area);

}

}

listing 6

// Demonstrate the if.

using System;

class IfDemo {

public static void Main() {

int a, b, c;

a = 2;

b = 3;

if(a < b) Console.WriteLine("a is less than b");

// this won't display anything

if(a == b) Console.WriteLine("you won't see this");

Console.WriteLine();

c = a - b; // c contains -1

Console.WriteLine("c contains -1");

if(c >= 0) Console.WriteLine("c is non-negative");

if(c < 0) Console.WriteLine("c is negative");

Console.WriteLine();

c = b - a; // c now contains 1

Console.WriteLine("c contains 1");

if(c >= 0) Console.WriteLine("c is non-negative");

if(c < 0) Console.WriteLine("c is negative");

}

}

listing 7

// Demonstrate the for loop.

using System;

class ForDemo {

public static void Main() {

int count;

for(count = 0; count < 5; count = count+1)

Console.WriteLine("This is count: " + count);

Console.WriteLine("Done!");

}

}

listing 8

// Demonstrate a block of code.

using System;

class BlockDemo {

public static void Main() {

int i, j, d;

i = 5;

j = 10;

// the target of this if is a block

if(i != 0) {

Console.WriteLine("i does not equal zero");

d = j / i;

Console.WriteLine("j / i is " + d);

}

}

}

listing 9

// Compute the sum and product of the numbers from 1 to 10.

using System;

class ProdSum {

public static void Main() {

int prod;

int sum;

int i;

sum = 0;

prod = 1;

for(i=1; i <= 10; i++) {

sum = sum + i;

prod = prod * i;

}

Console.WriteLine("Sum is " + sum);

Console.WriteLine("Product is " + prod);

}

}

listing 10

// Demonstrate an @ identifier.

using System;

class IdTest {

public static void Main() {

int @if; // use if as an identifier

for(@if = 0; @if < 10; @if++)

Console.WriteLine("@if is " + @if);

}

}

listing 1

// Compute the distance from the Earth to the sun, in inches.

using System;

class Inches {

public static void Main() {

long inches;

long miles;

miles = 93000000; // 93,000,000 miles to the sun

// 5,280 feet in a mile, 12 inches in a foot

inches = miles * 5280 * 12;

Console.WriteLine("Distance to the sun: " +

inches + " inches.");

}

}

listing 2

// Use byte.

using System;

class Use_byte {

public static void Main() {

byte x;

int sum;

sum = 0;

for(x = 1; x <= 100; x++)

sum = sum + x;

Console.WriteLine("Summation of 100 is " + sum);

}

}

listing 3

// Find the radius of a circle given its area.

using System;

class FindRadius {

public static void Main() {

Double r;

Double area;

area = 10.0;

r = Math.Sqrt(area / 3.1416);

Console.WriteLine("Radius is " + r);

}

}

listing 4

// Demonstrate Math.Sin(), Math.Cos(), and Math.Tan().

using System;

class Trigonometry {

public static void Main() {

Double theta; // angle in radians

for(theta = 0.1; theta <= 1.0; theta = theta + 0.1) {

Console.WriteLine("Sine of " + theta + " is " +

Math.Sin(theta));

Console.WriteLine("Cosine of " + theta + " is " +

Math.Cos(theta));

Console.WriteLine("Tangent of " + theta + " is " +

Math.Tan(theta));

Console.WriteLine();

}

}

}

listing 5

// Use the decimal type to compute a discount.

using System;

class UseDecimal {

public static void Main() {

decimal price;

decimal discount;

decimal discounted_price;

// compute discounted price

price = 19.95m;

discount = 0.15m; // discount rate is 15%

discounted_price = price - ( price * discount);

Console.WriteLine("Discounted price: $" + discounted_price);

}

}

listing 6

/*

Use the decimal type to compute the future value

of an investment.

*/

using System;

class FutVal {

public static void Main() {

decimal amount;

decimal rate_of_return;

int years, i;

amount = 1000.0M;

rate_of_return = 0.07M;

years = 10;

Console.WriteLine("Original investment: $" + amount);

Console.WriteLine("Rate of return: " + rate_of_return);

Console.WriteLine("Over " + years + " years");

for(i = 0; i < years; i++)

amount = amount + (amount * rate_of_return);

Console.WriteLine("Future value is $" + amount);

}

}

listing 7

// Demonstrate bool values.

using System;

class BoolDemo {

public static void Main() {

bool b;

b = false;

Console.WriteLine("b is " + b);

b = true;

Console.WriteLine("b is " + b);

// a bool value can control the if statement

if(b) Console.WriteLine("This is executed.");

b = false;

if(b) Console.WriteLine("This is not executed.");

// outcome of a relational operator is a bool value

Console.WriteLine("10 > 9 is " + (10 > 9));

}

}

listing 8

// Use format commands.

using System;

class DisplayOptions {

public static void Main() {

int i;

Console.WriteLine("Value\tSquared\tCubed");

for(i = 1; i < 10; i++)

Console.WriteLine("{0}\t{1}\t{2}",

i, i*i, i*i*i);

}

}

listing 9

/*

Use the C format specifier to output dollars and cents.

*/

using System;

class UseDecimal {

public static void Main() {

decimal price;

decimal discount;

decimal discounted_price;

// compute discounted price

price = 19.95m;

discount = 0.15m; // discount rate is 15%

discounted_price = price - ( price * discount);

Console.WriteLine("Discounted price: {0:C}", discounted_price);

}

}

listing 10

// Demonstrate escape sequences in strings.

using System;

class StrDemo {

public static void Main() {

Console.WriteLine("Line One\nLine Two\nLine Three");

Console.WriteLine("One\tTwo\tThree");

Console.WriteLine("Four\tFive\tSix");

// embed quotes

Console.WriteLine("\"Why?\", he asked.");

}

}

listing 11

// Demonstrate verbatim literal strings.

using System;

class Verbatim {

public static void Main() {

Console.WriteLine(@"This is a verbatim

string literal

that spans several lines.

");

Console.WriteLine(@"Here is some tabbed output:

1 2 3 4

5 6 7 8

");

Console.WriteLine(@"Programmers say, ""I like C#.""");

}

}

listing 12

// Demonstrate dynamic initialization.

using System;

class DynInit {

public static void Main() {

double s1 = 4.0, s2 = 5.0; // length of sides

// dynamically initialize hypot

double hypot = Math.Sqrt( (s1 * s1) + (s2 * s2) );

Console.Write("Hypotenuse of triangle with sides " +

s1 + " by " + s2 + " is ");

Console.WriteLine("{0:#.###}.", hypot);

}

}

listing 13

// Demonstrate block scope.

using System;

class ScopeDemo {

public static void Main() {

int x; // known to all code within Main()

x = 10;

if(x == 10) { // start new scope

int y = 20; // known only to this block

// x and y both known here.

Console.WriteLine("x and y: " + x + " " + y);

x = y * 2;

}

// y = 100; // Error! y not known here

// x is still known here.

Console.WriteLine("x is " + x);

}

}

listing 14

// Demonstrate lifetime of a variable.

using System;

class VarInitDemo {

public static void Main() {

int x;

for(x = 0; x < 3; x++) {

int y = -1; // y is initialized each time block is entered

Console.WriteLine("y is: " + y); // this always prints -1

y = 100;

Console.WriteLine("y is now: " + y);

}

}

}

listing 15

/*

This program attempts to declare a variable

in an inner scope with the same name as one

defined in an outer scope.

*** This program will not compile. ***

*/

using System;

class NestVar {

public static void Main() {

int count;

for(count = 0; count < 10; count = count+1) {

Console.WriteLine("This is count: " + count);

int count; // illegal!!!

for(count = 0; count < 2; count++)

Console.WriteLine("This program is in error!");

}

}

}

listing 16

// Demonstrate automatic conversion from long to double.

using System;

class LtoD {

public static void Main() {

long L;

double D;

L = 100123285L;

D = L;

Console.WriteLine("L and D: " + L + " " + D);

}

}

listing 17

// *** This program will not compile. ***

using System;

class LtoD {

public static void Main() {

long L;

double D;

D = 100123285.0;

L = D; // Illegal!!!

Console.WriteLine("L and D: " + L + " " + D);

}

}

listing 18

// Demonstrate casting.

using System;

class CastDemo {

public static void Main() {

double x, y;

byte b;

int i;

char ch;

uint u;

short s;

long l;

x = 10.0;

y = 3.0;

// cast an int into a double

i = (int) (x / y); // cast double to int, fractional component lost

Console.WriteLine("Integer outcome of x / y: " + i);

Console.WriteLine();

// cast an int into a byte, no data lost

i = 255;

b = (byte) i;

Console.WriteLine("b after assigning 255: " + b +

" -- no data lost.");

// cast an int into a byte, data lost

i = 257;

b = (byte) i;

Console.WriteLine("b after assigning 257: " + b +

" -- data lost.");

Console.WriteLine();

// cast a uint into a short, no data lost

u = 32000;

s = (short) u;

Console.WriteLine("s after assigning 32000: " + s +

" -- no data lost.");

// cast a uint into a short, data lost

u = 64000;

s = (short) u;

Console.WriteLine("s after assigning 64000: " + s +

" -- data lost.");

Console.WriteLine();

// cast a long into a uint, no data lost

l = 64000;

u = (uint) l;

Console.WriteLine("u after assigning 64000: " + u +

" -- no data lost.");

// cast a long into a uint, data lost

l = -12;

u = (uint) l;

Console.WriteLine("u after assigning -12: " + u +

" -- data lost.");

Console.WriteLine();

// cast an int into a char

b = 88; // ASCII code for X

ch = (char) b;

Console.WriteLine("ch after assigning 88: " + ch);

}

}

listing 19

// A promotion surprise!

using System;

class PromDemo {

public static void Main() {

byte b;

b = 10;

b = (byte) (b * b); // cast needed!!

Console.WriteLine("b: "+ b);

}

}

listing 20

// Using casts in an expression.

using System;

class CastExpr {

public static void Main() {

double n;

for(n = 1.0; n <= 10; n++) {

Console.WriteLine("The square root of {0} is {1}",

n, Math.Sqrt(n));

Console.WriteLine("Whole number part: {0}" ,

(int) Math.Sqrt(n));

Console.WriteLine("Fractional part: {0}",

Math.Sqrt(n) - (int) Math.Sqrt(n) );

Console.WriteLine();

}

}

}

listing 1

// Demonstrate the % operator.

using System;

class ModDemo {

public static void Main() {

int iresult, irem;

double dresult, drem;

iresult = 10 / 3;

irem = 10 % 3;

dresult = 10.0 / 3.0;

drem = 10.0 % 3.0;

Console.WriteLine("Result and remainder of 10 / 3: " +

iresult + " " + irem);

Console.WriteLine("Result and remainder of 10.0 / 3.0: " +

dresult + " " + drem);

}

}

listing 2

/*

Demonstrate the difference between prefix

postfix forms of ++.

*/

using System;

class PrePostDemo {

public static void Main() {

int x, y;

int i;

x = 1;

Console.WriteLine("Series generated using y = x + x++;");

for(i = 0; i < 10; i++) {

y = x + x++; // postfix ++

Console.WriteLine(y + " ");

}

Console.WriteLine();

x = 1;

Console.WriteLine("Series generated using y = x + ++x;");

for(i = 0; i < 10; i++) {

y = x + ++x; // prefix ++

Console.WriteLine(y + " ");

}

Console.WriteLine();

}

}

listing 3

// Demonstrate the relational and logical operators.

using System;

class RelLogOps {

public static void Main() {

int i, j;

bool b1, b2;

i = 10;

j = 11;

if(i < j) Console.WriteLine("i < j");

if(i <= j) Console.WriteLine("i <= j");

if(i != j) Console.WriteLine("i != j");

if(i == j) Console.WriteLine("this won't execute");

if(i >= j) Console.WriteLine("this won't execute");

if(i > j) Console.WriteLine("this won't execute");

b1 = true;

b2 = false;

if(b1 & b2) Console.WriteLine("this won't execute");

if(!(b1 & b2)) Console.WriteLine("!(b1 & b2) is true");

if(b1 | b2) Console.WriteLine("b1 | b2 is true");

if(b1 ^ b2) Console.WriteLine("b1 ^ b2 is true");

}

}

listing 4

// Create an implication operator in C#.

using System;

class Implication {

public static void Main() {

bool p=false, q=false;

int i, j;

for(i = 0; i < 2; i++) {

for(j = 0; j < 2; j++) {

if(i==0) p = true;

if(i==1) p = false;

if(j==0) q = true;

if(j==1) q = false;

Console.WriteLine("p is " + p + ", q is " + q);

if(!p | q) Console.WriteLine(p + " implies " + q +

" is " + true);

Console.WriteLine();

}

}

}

}

listing 5

// Demonstrate the short-circuit operators.

using System;

class SCops {

public static void Main() {

int n, d;

n = 10;

d = 2;

if(d != 0 && (n % d) == 0)

Console.WriteLine(d + " is a factor of " + n);

d = 0; // now, set d to zero

// Since d is zero, the second operand is not evaluated.

if(d != 0 && (n % d) == 0)

Console.WriteLine(d + " is a factor of " + n);

/* Now, try the same thing without short-circuit operator.

This will cause a divide-by-zero error. */

if(d != 0 & (n % d) == 0)

Console.WriteLine(d + " is a factor of " + n);

}

}

listing 6

// Side-effects can be important.

using System;

class SideEffects {

public static void Main() {

int i;

bool someCondition = false;

i = 0;

/* Here, i is still incremented even though

the if statement fails. */

if(someCondition & (++i < 100))

Console.WriteLine("this won't be displayed");

Console.WriteLine("if statement executed: " + i); // displays 1

/* In this case, i is not incremented because

the short-circuit operator skips the increment. */

if(someCondition && (++i < 100))

Console.WriteLine("this won't be displayed");

Console.WriteLine("if statement executed: " + i); // still 1 !!

}

}

listing 7

// Use bitwise AND to make a number even.

using System;

class MakeEven {

public static void Main() {

ushort num;

ushort i;

for(i = 1; i <= 10; i++) {

num = i;

Console.WriteLine("num: " + num);

num = (ushort) (num & 0xFFFE); // num & 1111 1110

Console.WriteLine("num after turning off bit zero: "

+ num + "\n");

}

}

}

listing 8

// Use bitwise AND to determine if a number is odd.

using System;

class IsOdd {

public static void Main() {

ushort num;

num = 10;

if((num & 1) == 1)

Console.WriteLine("This won't display.");

num = 11;

if((num & 1) == 1)

Console.WriteLine(num + " is odd.");

}

}

listing 9

// Display the bits within a byte.

using System;

class ShowBits {

public static void Main() {

int t;

byte val;

val = 123;

for(t=128; t > 0; t = t/2) {

if((val & t) != 0) Console.Write("1 ");

if((val & t) == 0) Console.Write("0 ");

}

}

}

listing 10

// Use bitwise OR to make a number odd.

using System;

class MakeOdd {

public static void Main() {

ushort num;

ushort i;

for(i = 1; i <= 10; i++) {

num = i;

Console.WriteLine("num: " + num);

num = (ushort) (num | 1); // num | 0000 0001

Console.WriteLine("num after turning on bit zero: "

+ num + "\n");

}

}

}

listing 11

// Use XOR to encode and decode a message.

using System;

class Encode {

public static void Main() {

char ch1 = 'H';

char ch2 = 'i';

char ch3 = '!';

int key = 88;

Console.WriteLine("Original message: " + ch1 + ch2 + ch3);

// encode the message

ch1 = (char) (ch1 ^ key);

ch2 = (char) (ch2 ^ key);

ch3 = (char) (ch3 ^ key);

Console.WriteLine("Encoded message: " + ch1 + ch2 + ch3);

// decode the message

ch1 = (char) (ch1 ^ key);

ch2 = (char) (ch2 ^ key);

ch3 = (char) (ch3 ^ key);

Console.WriteLine("Encoded message: " + ch1 + ch2 + ch3);

}

}

listing 12

// Demonstrate the bitwise NOT.

using System;

class NotDemo {

public static void Main() {

sbyte b = -34;

for(int t=128; t > 0; t = t/2) {

if((b & t) != 0) Console.Write("1 ");

if((b & t) == 0) Console.Write("0 ");

}

Console.WriteLine();

// reverse all bits

b = (sbyte) ~b;

for(int t=128; t > 0; t = t/2) {

if((b & t) != 0) Console.Write("1 ");

if((b & t) == 0) Console.Write("0 ");

}

}

}

listing 13

// Demonstrate the shift << and >> operators.

using System;

class ShiftDemo {

public static void Main() {

int val = 1;

for(int i = 0; i < 8; i++) {

for(int t=128; t > 0; t = t/2) {

if((val & t) != 0) Console.Write("1 ");

if((val & t) == 0) Console.Write("0 ");

}

Console.WriteLine();

val = val << 1; // left shift

}

Console.WriteLine();

val = 128;

for(int i = 0; i < 8; i++) {

for(int t=128; t > 0; t = t/2) {

if((val & t) != 0) Console.Write("1 ");

if((val & t) == 0) Console.Write("0 ");

}

Console.WriteLine();

val = val >> 1; // right shift

}

}

}

listing 14

// Use the shift operators to multiply and divide by 2.

using System;

class MultDiv {

public static void Main() {

int n;

n = 10;

Console.WriteLine("Value of n: " + n);

// multiply by 2

n = n << 1;

Console.WriteLine("Value of n after n = n * 2: " + n);

// multiply by 4

n = n << 2;

Console.WriteLine("Value of n after n = n * 4: " + n);

// divide by 2

n = n >> 1;

Console.WriteLine("Value of n after n = n / 2: " + n);

// divide by 4

n = n >> 2;

Console.WriteLine("Value of n after n = n / 4: " + n);

Console.WriteLine();

// reset n

n = 10;

Console.WriteLine("Value of n: " + n);

// multiply by 2, 30 times

n = n << 30; // data is lost

Console.WriteLine("Value of n after left-shifting 30 places: " + n);

}

}

listing 15

// Prevent a division by zero using the ?.

using System;

class NoZeroDiv {

public static void Main() {

int result;

for(int i = -5; i < 6; i++) {

result = i != 0 ? 100 / i : 0;

if(i != 0)

Console.WriteLine("100 / " + i + " is " + result);

}

}

}

listing 16

// Prevent a division by zero using the ?.

using System;

class NoZeroDiv2 {

public static void Main() {

for(int i = -5; i < 6; i++)

if(i != 0 ? true : false)

Console.WriteLine("100 / " + i +

" is " + 100 / i);

}

}

listing 1

// Determine if a value is positive or negative.

using System;

class PosNeg {

public static void Main() {

int i;

for(i=-5; i <= 5; i++) {

Console.Write("Testing " + i + ": ");

if(i < 0) Console.WriteLine("negative");

else Console.WriteLine("positive");

}

}

}

listing 2

// Determine if a value is positive, negative, or zero.

using System;

class PosNegZero {

public static void Main() {

int i;

for(i=-5; i <= 5; i++) {

Console.Write("Testing " + i + ": ");

if(i < 0) Console.WriteLine("negative");

else if(i == 0) Console.WriteLine("no sign");

else Console.WriteLine("positive");

}

}

}

listing 3

// Determine smallest single-digit factor.

using System;

class Ladder {

public static void Main() {

int num;

for(num = 2; num < 12; num++) {

if((num % 2) == 0)

Console.WriteLine("Smallest factor of " + num + " is 2.");

else if((num % 3) == 0)

Console.WriteLine("Smallest factor of " + num + " is 3.");

else if((num % 5) == 0)

Console.WriteLine("Smallest factor of " + num + " is 5.");

else if((num % 7) == 0)

Console.WriteLine("Smallest factor of " + num + " is 7.");

else

Console.WriteLine(num + " is not divisible by 2, 3, 5, or 7.");

}

}

}

listing 4

// Demonstrate the switch.

using System;

class SwitchDemo {

public static void Main() {

int i;

for(i=0; i<10; i++)

switch(i) {

case 0:

Console.WriteLine("i is zero");

break;

case 1:

Console.WriteLine("i is one");

break;

case 2:

Console.WriteLine("i is two");

break;

case 3:

Console.WriteLine("i is three");

break;

case 4:

Console.WriteLine("i is four");

break;

default:

Console.WriteLine("i is five or more");

break;

}

}

}

listing 5

// Use a char to control the switch.

using System;

class SwitchDemo2 {

public static void Main() {

char ch;

for(ch='A'; ch<= 'E'; ch++)

switch(ch) {

case 'A':

Console.WriteLine("ch is A");

break;

case 'B':

Console.WriteLine("ch is B");

break;

case 'C':

Console.WriteLine("ch is C");

break;

case 'D':

Console.WriteLine("ch is D");

break;

case 'E':

Console.WriteLine("ch is E");

break;

}

}

}

listing 6

// Empty cases can fall through.

using System;

class EmptyCasesCanFall {

public static void Main() {

int i;

for(i=1; i < 5; i++)

switch(i) {

case 1:

case 2:

case 3: Console.WriteLine("i is 1, 2 or 3");

break;

case 4: Console.WriteLine("i is 4");

break;

}

}

}

listing 7

// A negatively running for loop.

using System;

class DecrFor {

public static void Main() {

int x;

for(x = 100; x > -100; x -= 5)

Console.WriteLine(x);

}

}

listing 8

/*

Determine if a number is prime. If it is not,

then display its largest factor.

*/

using System;

class FindPrimes {

public static void Main() {

int num;

int i;

int factor;

bool isprime;

for(num = 2; num < 20; num++) {

isprime = true;

factor = 0;

// see if num is evenly divisible

for(i=2; i <= num/2; i++) {

if((num % i) == 0) {

// num is evenly divisible -- not prime

isprime = false;

factor = i;

}

}

if(isprime)

Console.WriteLine(num + " is prime.");

else

Console.WriteLine("Largest factor of " + num +

" is " + factor);

}

}

}

listing 9

// Use commas in a for statement.

using System;

class Comma {

public static void Main() {

int i, j;

for(i=0, j=10; i < j; i++, j--)

Console.WriteLine("i and j: " + i + " " + j);

}

}

listing 10

/*

Use commas in a for statement to find

the largest and smallest factor of a number.

*/

using System;

class Comma {

public static void Main() {

int i, j;

int smallest, largest;

int num;

num = 100;

smallest = largest = 1;

for(i=2, j=num/2; (i <= num/2) & (j >= 2); i++, j--) {

if((smallest == 1) & ((num % i) == 0))

smallest = i;

if((largest == 1) & ((num % j) == 0))

largest = j;

}

Console.WriteLine("Largest factor: " + largest);

Console.WriteLine("Smallest factor: " + smallest);

}

}

listing 11

// Loop condition can be any bool expression.

using System;

class forDemo {

public static void Main() {

int i, j;

bool done = false;

for(i=0, j=100; !done; i++, j--) {

if(i*i >= j) done = true;

Console.WriteLine("i, j: " + i + " " + j);

}

}

}

listing 12

// Parts of the for can be empty.

using System;

class Empty {

public static void Main() {

int i;

for(i = 0; i < 10; ) {

Console.WriteLine("Pass #" + i);

i++; // increment loop control var

}

}

}

listing 13

// Move more out of the for loop.

using System;

class Empty2 {

public static void Main() {

int i;

i = 0; // move initialization out of loop

for(; i < 10; ) {

Console.WriteLine("Pass #" + i);

i++; // increment loop control var

}

}

}

listing 14

// The body of a loop can be empty.

using System;

class Empty3 {

public static void Main() {

int i;

int sum = 0;

// sum the numbers through 5

for(i = 1; i <= 5; sum += i++) ;

Console.WriteLine("Sum is " + sum);

}

}

listing 15

// Declare loop control variable inside the for.

using System;

class ForVar {

public static void Main() {

int sum = 0;

int fact = 1;

// Compute the factorial of the numbers through 5.

for(int i = 1; i <= 5; i++) {

sum += i; // i is known throughout the loop

fact *= i;

}

// But, i is not known here.

Console.WriteLine("Sum is " + sum);

Console.WriteLine("Factorial is " + fact);

}

}

listing 16

// Compute the order of magnitude of an integer

using System;

class WhileDemo {

public static void Main() {

int num;

int mag;

num = 435679;

mag = 0;

Console.WriteLine("Number: " + num);

while(num > 0) {

mag++;

num = num / 10;

};

Console.WriteLine("Magnitude: " + mag);

}

}

listing 17

// Compute integer powers of 2.

using System;

class Power {

public static void Main() {

int e;

int result;

for(int i=0; i < 10; i++) {

result = 1;

e = i;

while(e > 0) {

result *= 2;

e--;

}

Console.WriteLine("2 to the " + i +

" power is " + result);

}

}

}

listing 18

// Display the digits of an integer in reverse order.

using System;

class DoWhileDemo {

public static void Main() {

int num;

int nextdigit;

num = 198;

Console.WriteLine("Number: " + num);

Console.Write("Number in reverse order: ");

do {

nextdigit = num % 10;

Console.Write(nextdigit);

num = num / 10;

} while(num > 0);

Console.WriteLine();

}

}

listing 19

// Using break to exit a loop.

using System;

class BreakDemo {

public static void Main() {

// use break to exit this loop

for(int i=-10; i <= 10; i++) {

if(i > 0) break; // terminate loop when i is positive

Console.Write(i + " ");

}

Console.WriteLine("Done");

}

}

listing 20

// Using break to exit a do-while loop.

using System;

class BreakDemo2 {

public static void Main() {

int i;

i = -10;

do {

if(i > 0) break;

Console.Write(i + " ");

i++;

} while(i <= 10);

Console.WriteLine("Done");

}

}

listing 21

// Find the smallest factor of a value.

using System;

class FindSmallestFactor {

public static void Main() {

int factor = 1;

int num = 1000;

for(int i=2; i < num/2; i++) {

if((num%i) == 0) {

factor = i;

break; // stop loop when factor is found

}

}

Console.WriteLine("Smallest factor is " + factor);

}

}

listing 22

// Using break with nested loops.

using System;

class BreakNested {

public static void Main() {

for(int i=0; i<3; i++) {

Console.WriteLine("Outer loop count: " + i);

Console.Write(" Inner loop count: ");

int t = 0;

while(t < 100) {

if(t == 10) break; // terminate loop if t is 10

Console.Write(t + " ");

t++;

}

Console.WriteLine();

}

Console.WriteLine("Loops complete.");

}

}

listing 23

// Use continue.

using System;

class ContDemo {

public static void Main() {

// print even numbers between 0 and 100

for(int i = 0; i <= 100; i++) {

if((i%2) != 0) continue; // iterate

Console.WriteLine(i);

}

}

}

listing 24

// Use goto with a switch.

using System;

class SwitchGoto {

public static void Main() {

for(int i=1; i < 5; i++) {

switch(i) {

case 1:

Console.WriteLine("In case 1");

goto case 3;

case 2:

Console.WriteLine("In case 2");

goto case 1;

case 3:

Console.WriteLine("In case 3");

goto default;

default:

Console.WriteLine("In default");

break;

}

Console.WriteLine();

}

// goto case 1; // Error! Can't jump into a switch.

}

}

listing 25

// Demonstrate the goto.

using System;

class Use_goto {

public static void Main() {

int i=0, j=0, k=0;

for(i=0; i < 10; i++) {

for(j=0; j < 10; j++ ) {

for(k=0; k < 10; k++) {

Console.WriteLine("i, j, k: " + i + " " + j + " " + k);

if(k == 3) goto stop;

}

}

}

stop:

Console.WriteLine("Stopped! i, j, k: " + i + ", " + j + " " + k);

}

}

listing 1

// A program that uses the Building class.

using System;

class Building {

public int floors; // number of floors

public int area; // total square footage of building

public int occupants; // number of occupants

}

// This class declares an object of type Building.

class BuildingDemo {

public static void Main() {

Building house = new Building(); // create a Building object

int areaPP; // area per person

// assign values to fields in house

house.occupants = 4;

house.area = 2500;

house.floors = 2;

// compute the area per person

areaPP = house.area / house.occupants;

Console.WriteLine("house has:\n " +

house.floors + " floors\n " +

house.occupants + " occupants\n " +

house.area + " total area\n " +

areaPP + " area per person");

}

}

listing 2

// This program creates two Building objects.

using System;

class Building {

public int floors; // number of floors

public int area; // total square footage of building

public int occupants; // number of occupants

}

// This class declares two objects of type Building.

class BuildingDemo {

public static void Main() {

Building house = new Building();

Building office = new Building();

int areaPP; // area per person

// assign values to fields in house

house.occupants = 4;

house.area = 2500;

house.floors = 2;

// assign values to fields in office

office.occupants = 25;

office.area = 4200;

office.floors = 3;

// compute the area per person in house

areaPP = house.area / house.occupants;

Console.WriteLine("house has:\n " +

house.floors + " floors\n " +

house.occupants + " occupants\n " +

house.area + " total area\n " +

areaPP + " area per person");

Console.WriteLine();

// compute the area per person in office

areaPP = office.area / office.occupants;

Console.WriteLine("office has:\n " +

office.floors + " floors\n " +

office.occupants + " occupants\n " +

office.area + " total area\n " +

areaPP + " area per person");

}

}

listing 3

// Add a method to Building.

using System;

class Building {

public int floors; // number of floors

public int area; // total square footage of building

public int occupants; // number of occupants

// Display the area per person.

public void areaPerPerson() {

Console.WriteLine(" " + area / occupants +

" area per person");

}

}

// Use the areaPerPerson() method.

class BuildingDemo {

public static void Main() {

Building house = new Building();

Building office = new Building();

// assign values to fields in house

house.occupants = 4;

house.area = 2500;

house.floors = 2;

// assign values to fields in office

office.occupants = 25;

office.area = 4200;

office.floors = 3;

Console.WriteLine("house has:\n " +

house.floors + " floors\n " +

house.occupants + " occupants\n " +

house.area + " total area");

house.areaPerPerson();

Console.WriteLine();

Console.WriteLine("office has:\n " +

office.floors + " floors\n " +

office.occupants + " occupants\n " +

office.area + " total area");

office.areaPerPerson();

}

}

listing 4

// Return a value from areaPerPerson().

using System;

class Building {

public int floors; // number of floors

public int area; // total square footage of building

public int occupants; // number of occupants

// Return the area per person.

public int areaPerPerson() {

return area / occupants;

}

}

// Use the return value from areaPerPerson().

class BuildingDemo {

public static void Main() {

Building house = new Building();

Building office = new Building();

int areaPP; // area per person

// assign values to fields in house

house.occupants = 4;

house.area = 2500;

house.floors = 2;

// assign values to fields in office

office.occupants = 25;

office.area = 4200;

office.floors = 3;

// obtain area per person for house

areaPP = house.areaPerPerson();

Console.WriteLine("house has:\n " +

house.floors + " floors\n " +

house.occupants + " occupants\n " +

house.area + " total area\n " +

areaPP + " area per person");

Console.WriteLine();

// obtain area per person for office

areaPP = office.areaPerPerson();

Console.WriteLine("office has:\n " +

office.floors + " floors\n " +

office.occupants + " occupants\n " +

office.area + " total area\n " +

areaPP + " area per person");

}

}

listing 5

// A simple example that uses a parameter.

using System;

class ChkNum {

// Return true if x is prime.

public bool isPrime(int x) {

for(int i=2; i <= x/i; i++)

if((x %i) == 0) return false;

return true;

}

}

class ParmDemo {

public static void Main() {

ChkNum ob = new ChkNum();

for(int i=1; i < 10; i++)

if(ob.isPrime(i)) Console.WriteLine(i + " is prime.");

else Console.WriteLine(i + " is not prime.");

}

}

listing 6

// Add a method that takes two arguments.

using System;

class ChkNum {

// Return true if x is prime.

public bool isPrime(int x) {

for(int i=2; i <= x/i; i++)

if((x %i) == 0) return false;

return true;

}

// Return the least common factor.

public int leastComFactor(int a, int b) {

int max;

if(isPrime(a) | isPrime(b)) return 1;

max = a < b ? a : b;

for(int i=2; i <= max/2; i++)

if(((a%i) == 0) & ((b%i) == 0)) return i;

return 1;

}

}

class ParmDemo {

public static void Main() {

ChkNum ob = new ChkNum();

int a, b;

for(int i=1; i < 10; i++)

if(ob.isPrime(i)) Console.WriteLine(i + " is prime.");

else Console.WriteLine(i + " is not prime.");

a = 7;

b = 8;

Console.WriteLine("Least common factor for " +

a + " and " + b + " is " +

ob.leastComFactor(a, b));

a = 100;

b = 8;

Console.WriteLine("Least common factor for " +

a + " and " + b + " is " +

ob.leastComFactor(a, b));

a = 100;

b = 75;

Console.WriteLine("Least common factor for " +

a + " and " + b + " is " +

ob.leastComFactor(a, b));

}

}

listing 7

/*

Add a parameterized method that computes the

maximum number of people that can occupy a

building assuming each needs a specified

minimum space.

*/

using System;

class Building {

public int floors; // number of floors

public int area; // total square footage of building

public int occupants; // number of occupants

// Return the area per person.

public int areaPerPerson() {

return area / occupants;

}

/* Return the maximum number of occupants if each

is to have at least the specified minimum area. */

public int maxOccupant(int minArea) {

return area / minArea;

}

}

// Use maxOccupant().

class BuildingDemo {

public static void Main() {

Building house = new Building();

Building office = new Building();

// assign values to fields in house

house.occupants = 4;

house.area = 2500;

house.floors = 2;

// assign values to fields in office

office.occupants = 25;

office.area = 4200;

office.floors = 3;

Console.WriteLine("Maximum occupants for house if each has " +

300 + " square feet: " +

house.maxOccupant(300));

Console.WriteLine("Maximum occupants for office if each has " +

300 + " square feet: " +

office.maxOccupant(300));

}

}

listing 8

public void m() {

char a, b;

// ...

if(a==b) {

Console.WriteLine("equal");

return;

} else {

Console.WriteLine("not equal");

return;

}

Console.WriteLine("this is unreachable");

}

listing 9

// A simple constructor.

using System;

class MyClass {

public int x;

public MyClass() {

x = 10;

}

}

class ConsDemo {

public static void Main() {

MyClass t1 = new MyClass();

MyClass t2 = new MyClass();

Console.WriteLine(t1.x + " " + t2.x);

}

}

listing 10

// A parameterized constructor.

using System;

class MyClass {

public int x;

public MyClass(int i) {

x = i;

}

}

class ParmConsDemo {

public static void Main() {

MyClass t1 = new MyClass(10);

MyClass t2 = new MyClass(88);

Console.WriteLine(t1.x + " " + t2.x);

}

}

listing 11

// Add a constructor to Building.

using System;

class Building {

public int floors; // number of floors

public int area; // total square footage of building

public int occupants; // number of occupants

public Building(int f, int a, int o) {

floors = f;

area = a;

occupants = o;

}

// Display the area per person.

public int areaPerPerson() {

return area / occupants;

}

/* Return the maximum number of occupants if each

is to have at least the specified minimum area. */

public int maxOccupant(int minArea) {

return area / minArea;

}

}

// Use the parameterized Building constructor.

class BuildingDemo {

public static void Main() {

Building house = new Building(2, 2500, 4);

Building office = new Building(3, 4200, 25);

Console.WriteLine("Maximum occupants for house if each has " +

300 + " square feet: " +

house.maxOccupant(300));

Console.WriteLine("Maximum occupants for office if each has " +

300 + " square feet: " +

office.maxOccupant(300));

}

}

listing 12

// Use new with a value type.

using System;

class newValue {

public static void Main() {

int i = new int(); // initialize i to zero

Console.WriteLine("The value of i is: " + i);

}

}

listing 13

// Demonstrate a destructor.

using System;

class Destruct {

public int x;

public Destruct(int i) {

x = i;

}

// called when object is recycled

~Destruct() {

Console.WriteLine("Destructing " + x);

}

// generates an object that is immediately destroyed

public void generator(int i) {

Destruct o = new Destruct(i);

}

}

class DestructDemo {

public static void Main() {

int count;

Destruct ob = new Destruct(0);

/* Now, generate a large number of objects. At

some point, garbage collection will occur.

Note: you might need to increase the number

of objects generated in order to force

garbage collection. */

for(count=1; count < 100000; count++)

ob.generator(count);

Console.WriteLine("Done");

}

}

listing 14

using System;

class Rect {

public int width;

public int height;

public Rect(int w, int h) {

width = w;

height = h;

}

public int area() {

return width * height;

}

}

class UseRect {

public static void Main() {

Rect r1 = new Rect(4, 5);

Rect r2 = new Rect(7, 9);

Console.WriteLine("Area of r1: " + r1.area());

Console.WriteLine("Area of r2: " + r2.area());

}

}

listing 15

using System;

class Rect {

public int width;

public int height;

public Rect(int w, int h) {

this.width = w;

this.height = h;

}

public int area() {

return this.width * this.height;

}

}

class UseRect {

public static void Main() {

Rect r1 = new Rect(4, 5);

Rect r2 = new Rect(7, 9);

Console.WriteLine("Area of r1: " + r1.area());

Console.WriteLine("Area of r2: " + r2.area());

}

}

listing 1

// Demonstrate a one-dimensional array.

using System;

class ArrayDemo {

public static void Main() {

int[] sample = new int[10];

int i;

for(i = 0; i < 10; i = i+1)

sample[i] = i;

for(i = 0; i < 10; i = i+1)

Console.WriteLine("sample[" + i + "]: " +

sample[i]);

}

}

listing 2

// Compute the average of a set of values.

using System;

class Average {

public static void Main() {

int[] nums = new int[10];

int avg = 0;

nums[0] = 99;

nums[1] = 10;

nums[2] = 100;

nums[3] = 18;

nums[4] = 78;

nums[5] = 23;

nums[6] = 63;

nums[7] = 9;

nums[8] = 87;

nums[9] = 49;

for(int i=0; i < 10; i++)

avg = avg + nums[i];

avg = avg / 10;

Console.WriteLine("Average: " + avg);

}

}

listing 3

// Compute the average of a set of values.

using System;

class Average {

public static void Main() {

int[] nums = { 99, 10, 100, 18, 78, 23,

63, 9, 87, 49 };

int avg = 0;

for(int i=0; i < 10; i++)

avg = avg + nums[i];

avg = avg / 10;

Console.WriteLine("Average: " + avg);

}

}

listing 4

// Demonstrate an array overrun.

using System;

class ArrayErr {

public static void Main() {

int[] sample = new int[10];

int i;

// generate an array overrun

for(i = 0; i < 100; i = i+1)

sample[i] = i;

}

}

listing 5

// Demonstrate a two-dimensional array.

using System;

class TwoD {

public static void Main() {

int t, i;

int[,] table = new int[3, 4];

for(t=0; t < 3; ++t) {

for(i=0; i < 4; ++i) {

table[t,i] = (t*4)+i+1;

Console.Write(table[t,i] + " ");

}

Console.WriteLine();

}

}

}

listing 6

// Sum the values on a diagonal of a 3x3x3 matrix.

using System;

class ThreeDMatrix {

public static void Main() {

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

int sum = 0;

int n = 1;

for(int x=0; x < 3; x++)

for(int y=0; y < 3; y++)

for(int z=0; z < 3; z++)

m[x, y, z] = n++;

sum = m[0,0,0] + m[1,1,1] + m[2, 2, 2];

Console.WriteLine("Sum of first diagonal: " + sum);

}

}

listing 7

// Initialize a two-dimensional array.

using System;

class Squares {

public static void Main() {

int[,] sqrs = {

{ 1, 1 },

{ 2, 4 },

{ 3, 9 },

{ 4, 16 },

{ 5, 25 },

{ 6, 36 },

{ 7, 49 },

{ 8, 64 },

{ 9, 81 },

{ 10, 100 }

};

int i, j;

for(i=0; i < 10; i++) {

for(j=0; j < 2; j++)

Console.Write(sqrs[i,j] + " ");

Console.WriteLine();

}

}

}

listing 8

// Demonstrate jagged arrays.

using System;

class Jagged {

public static void Main() {

int[][] jagged = new int[3][];

jagged[0] = new int[4];

jagged[1] = new int[3];

jagged[2] = new int[5];

int i;

// store values in first array

for(i=0; i < 4; i++)

jagged[0][i] = i;

// store values in second array

for(i=0; i < 3; i++)

jagged[1][i] = i;

// store values in third array

for(i=0; i < 5; i++)

jagged[2][i] = i;

// display values in first array

for(i=0; i < 4; i++)

Console.Write(jagged[0][i] + " ");

Console.WriteLine();

// display values in second array

for(i=0; i < 3; i++)

Console.Write(jagged[1][i] + " ");

Console.WriteLine();

// display values in third array

for(i=0; i < 5; i++)

Console.Write(jagged[2][i] + " ");

Console.WriteLine();

}

}

listing 9

// Assigning array reference variables.

using System;

class AssignARef {

public static void Main() {

int i;

int[] nums1 = new int[10];

int[] nums2 = new int[10];

for(i=0; i < 10; i++) nums1[i] = i;

for(i=0; i < 10; i++) nums2[i] = -i;

Console.Write("Here is nums1: ");

for(i=0; i < 10; i++)

Console.Write(nums1[i] + " ");

Console.WriteLine();

Console.Write("Here is nums2: ");

for(i=0; i < 10; i++)

Console.Write(nums2[i] + " ");

Console.WriteLine();

nums2 = nums1; // now nums2 refers to nums1

Console.Write("Here is nums2 after assignment: ");

for(i=0; i < 10; i++)

Console.Write(nums2[i] + " ");

Console.WriteLine();

// now operate on nums1 array through nums2

nums2[3] = 99;

Console.Write("Here is nums1 after change through nums2: ");

for(i=0; i < 10; i++)

Console.Write(nums1[i] + " ");

Console.WriteLine();

}

}

listing 10

// Use the Length array property.

using System;

class LengthDemo {

public static void Main() {

int[] nums = new int[10];

Console.WriteLine("Length of nums is " + nums.Length);

// use Length to initialize nums

for(int i=0; i < nums.Length; i++)

nums[i] = i * i;

// now use Length to display nums

Console.Write("Here is nums: ");

for(int i=0; i < nums.Length; i++)

Console.Write(nums[i] + " ");

Console.WriteLine();

}

}

listing 11

// Use the Length array property on a 3-D array.

using System;

class LengthDemo3D {

public static void Main() {

int[,,] nums = new int[10, 5, 6];

Console.WriteLine("Length of nums is " + nums.Length);

}

}

listing 12

// Reverse an array.

using System;

class RevCopy {

public static void Main() {

int i,j;

int[] nums1 = new int[10];

int[] nums2 = new int[10];

for(i=0; i < nums1.Length; i++) nums1[i] = i;

Console.Write("Original contents: ");

for(i=0; i < nums2.Length; i++)

Console.Write(nums1[i] + " ");

Console.WriteLine();

// reverse copy nums1 to nums2

if(nums2.Length >= nums1.Length) // make sure nums2 is long enough

for(i=0, j=nums1.Length-1; i < nums1.Length; i++, j--)

nums2[j] = nums1[i];

Console.Write("Reversed contents: ");

for(i=0; i < nums2.Length; i++)

Console.Write(nums2[i] + " ");

Console.WriteLine();

}

}

listing 13

// Demonstrate Length with jagged arrays.

using System;

class Jagged {

public static void Main() {

int[][] network_nodes = new int[4][];

network_nodes[0] = new int[3];

network_nodes[1] = new int[7];

network_nodes[2] = new int[2];

network_nodes[3] = new int[5];

int i, j;

// fabricate some fake CPU usage data

for(i=0; i < network_nodes.Length; i++)

for(j=0; j < network_nodes[i].Length; j++)

network_nodes[i][j] = i * j + 70;

Console.WriteLine("Total number of network nodes: " +

network_nodes.Length + "\n");

for(i=0; i < network_nodes.Length; i++) {

for(j=0; j < network_nodes[i].Length; j++) {

Console.Write("CPU usage at node " + i +

" CPU " + j + ": ");

Console.Write(network_nodes[i][j] + "% ");

Console.WriteLine();

}

Console.WriteLine();

}

}

}

listing 14

// Use the foreach loop.

using System;

class ForeachDemo {

public static void Main() {

int sum = 0;

int[] nums = new int[10];

// give nums some values

for(int i = 0; i < 10; i++)

nums[i] = i;

// use foreach to display and sum the values

foreach(int x in nums) {

Console.WriteLine("Value is: " + x);

sum += x;

}

Console.WriteLine("Summation: " + sum);

}

}

listing 15

// Use break with a foreach.

using System;

class ForeachDemo {

public static void Main() {

int sum = 0;

int[] nums = new int[10];

// give nums some values

for(int i = 0; i < 10; i++)

nums[i] = i;

// use foreach to display and sum the values

foreach(int x in nums) {

Console.WriteLine("Value is: " + x);

sum += x;

if(x == 4) break; // stop the loop when 4 is obtained

}

Console.WriteLine("Summation of first 5 elements: " + sum);

}

}

listing 16

// Use foreach on a two-dimensional array.

using System;

class ForeachDemo2 {

public static void Main() {

int sum = 0;

int[,] nums = new int[3,5];

// give nums some values

for(int i = 0; i < 3; i++)

for(int j=0; j < 5; j++)

nums[i,j] = (i+1)*(j+1);

// use foreach to display and sum the values

foreach(int x in nums) {

Console.WriteLine("Value is: " + x);

sum += x;

}

Console.WriteLine("Summation: " + sum);

}

}

listing 17

// Search an array using foreach.

using System;

class Search {

public static void Main() {

int[] nums = new int[10];

int val;

bool found = false;

// give nums some values

for(int i = 0; i < 10; i++)

nums[i] = i;

val = 5;

// use foreach to search nums for key

foreach(int x in nums) {

if(x == val) {

found = true;

break;

}

}

if(found)

Console.WriteLine("Value found!");

}

}

listing 18

// Introduce string.

using System;

class StringDemo {

public static void Main() {

char[] charray = {'A', ' ', 's', 't', 'r', 'i', 'n', 'g', '.' };

string str1 = new string(charray);

string str2 = "Another string.";

Console.WriteLine(str1);

Console.WriteLine(str2);

}

}

listing 19

// Some string operations.

using System;

class StrOps {

public static void Main() {

string str1 =

"When it comes to .NET programming, C# is #1.";

string str2 = string.Copy(str1);

string str3 = "C# strings are powerful.";

string strUp, strLow;

int result, idx;

Console.WriteLine("str1: " + str1);

Console.WriteLine("Length of str1: " +

str1.Length);

// create upper- and lowercase versions of str1

strLow = str1.ToLower();

strUp = str1.ToUpper();

Console.WriteLine("Lowercase version of str1:\n " +

strLow);

Console.WriteLine("Uppercase version of str1:\n " +

strUp);

Console.WriteLine();

// display str1, one char at a time.

Console.WriteLine("Display str1, one char at a time.");

for(int i=0; i < str1.Length; i++)

Console.Write(str1[i]);

Console.WriteLine("\n");

// compare strings

if(str1 == str2)

Console.WriteLine("str1 == str2");

else

Console.WriteLine("str1 != str2");

if(str1 == str3)

Console.WriteLine("str1 == str3");

else

Console.WriteLine("str1 != str3");

result = str1.CompareTo(str3);

if(result == 0)

Console.WriteLine("str1 and str3 are equal");

else if(result < 0)

Console.WriteLine("str1 is less than str3");

else

Console.WriteLine("str1 is greater than str3");

Console.WriteLine();

// assign a new string to str2

str2 = "One Two Three One";

// search string

idx = str2.IndexOf("One");

Console.WriteLine("Index of first occurrence of One: " + idx);

idx = str2.LastIndexOf("One");

Console.WriteLine("Index of last occurrence of One: " + idx);

}

}

listing 20

// Demonstrate string arrays.

using System;

class StringArrays {

public static void Main() {

string[] str = { "This", "is", "a", "test." };

Console.WriteLine("Original array: ");

for(int i=0; i < str.Length; i++)

Console.Write(str[i] + " ");

Console.WriteLine("\n");

// change a string

str[1] = "was";

str[3] = "test, too!";

Console.WriteLine("Modified array: ");

for(int i=0; i < str.Length; i++)

Console.Write(str[i] + " ");

}

}

listing 21

// Display the digits of an integer using words.

using System;

class ConvertDigitsToWords {

public static void Main() {

int num;

int nextdigit;

int numdigits;

int[] n = new int[20];

string[] digits = { "zero", "one", "two",

"three", "four", "five",

"six", "seven", "eight",

"nine" };

num = 1908;

Console.WriteLine("Number: " + num);

Console.Write("Number in words: ");

nextdigit = 0;

numdigits = 0;

/* Get individual digits and store in n.

These digits are stored in reverse order. */

do {

nextdigit = num % 10;

n[numdigits] = nextdigit;

numdigits++;

num = num / 10;

} while(num > 0);

numdigits--;

// display words

for( ; numdigits >= 0; numdigits--)

Console.Write(digits[n[numdigits]] + " ");

Console.WriteLine();

}

}

listing 22

// Use Substring().

using System;

class SubStr {

public static void Main() {

string orgstr = "C# makes strings easy.";

// construct a substring

string substr = orgstr.Substring(5, 12);

Console.WriteLine("orgstr: " + orgstr);

Console.WriteLine("substr: " + substr);

}

}

listing 23

// A string can control a switch statement.

using System;

class StringSwitch {

public static void Main() {

string[] strs = { "one", "two", "three", "two", "one" };

foreach(string s in strs) {

switch(s) {

case "one":

Console.Write(1);

break;

case "two":

Console.Write(2);

break;

case "three":

Console.Write(3);

break;

}

}

Console.WriteLine();

}

}

listing 1

// Public vs private access.

using System;

class MyClass {

private int alpha; // private access explicitly specified

int beta; // private access by default

public int gamma; // public access

/* Methods to access alpha and beta. It is OK for a

member of a class to access a private member

of the same class.

*/

public void setAlpha(int a) {

alpha = a;

}

public int getAlpha() {

return alpha;

}

public void setBeta(int a) {

beta = a;

}

public int getBeta() {

return beta;

}

}

class AccessDemo {

public static void Main() {

MyClass ob = new MyClass();

/* Access to alpha and beta is allowed only

through methods. */

ob.setAlpha(-99);

ob.setBeta(19);

Console.WriteLine("ob.alpha is " + ob.getAlpha());

Console.WriteLine("ob.beta is " + ob.getBeta());

// You cannot access alpha or beta like this:

// ob.alpha = 10; // Wrong! alpha is private!

// ob.beta = 9; // Wrong! beta is private!

// It is OK to directly access gamma because it is public.

ob.gamma = 99;

}

}

listing 2

// A stack class for characters.

using System;

class Stack {

// these members are private

char[] stck; // holds the stack

int tos; // index of the top of the stack

// Construct an empty Stack given its size.

public Stack(int size) {

stck = new char[size]; // allocate memory for stack

tos = 0;

}

// Push characters onto the stack.

public void push(char ch) {

if(tos==stck.Length) {

Console.WriteLine(" -- Stack is full.");

return;

}

stck[tos] = ch;

tos++;

}

// Pop a character from the stack.

public char pop() {

if(tos==0) {

Console.WriteLine(" -- Stack is empty.");

return (char) 0;

}

tos--;

return stck[tos];

}

// Return true if the stack is full.

public bool full() {

return tos==stck.Length;

}

// Return true if the stack is empty.

public bool empty() {

return tos==0;

}

// Return total capacity of the stack.

public int capacity() {

return stck.Length;

}

// Return number of objects currently on the stack.

public int getNum() {

return tos;

}

}

listing 3

// Demonstrate the Stack class.

using System;

class StackDemo {

public static void Main() {

Stack stk1 = new Stack(10);

Stack stk2 = new Stack(10);

Stack stk3 = new Stack(10);

char ch;

int i;

// Put some characters into stk1.

Console.WriteLine("Push A through J onto stk1.");

for(i=0; !stk1.full(); i++)

stk1.push((char) ('A' + i));

if(stk1.full()) Console.WriteLine("stk1 is full.");

// Display the contents of stk1.

Console.Write("Contents of stk1: ");

while( !stk1.empty() ) {

ch = stk1.pop();

Console.Write(ch);

}

Console.WriteLine();

if(stk1.empty()) Console.WriteLine("stk1 is empty.\n");

// put more characters into stk1

Console.WriteLine("Again push A through J onto stk1.");

for(i=0; !stk1.full(); i++)

stk1.push((char) ('A' + i));

/* Now, pop from stk1 and push the element in stk2.

This causes stk2 to hold the elements in

reverse order. */

Console.WriteLine("Now, pop chars from stk1 and push " +

"them onto stk2.");

while( !stk1.empty() ) {

ch = stk1.pop();

stk2.push(ch);

}

Console.Write("Contents of stk2: ");

while( !stk2.empty() ) {

ch = stk2.pop();

Console.Write(ch);

}

Console.WriteLine("\n");

// put 5 characters into stack

Console.WriteLine("Put 5 characters on stk3.");

for(i=0; i < 5; i++)

stk3.push((char) ('A' + i));

Console.WriteLine("Capacity of stk3: " + stk3.capacity());

Console.WriteLine("Number of objects in stk3: " +

stk3.getNum());

}

}

listing 4

// References can be passed to methods.

using System;

class MyClass {

int alpha, beta;

public MyClass(int i, int j) {

alpha = i;

beta = j;

}

/* Return true if ob contains the same values

as the invoking object. */

public bool sameAs(MyClass ob) {

if((ob.alpha == alpha) & (ob.beta == beta))

return true;

else return false;

}

// Make a copy of ob.

public void copy(MyClass ob) {

alpha = ob.alpha;

beta = ob.beta;

}

public void show() {

Console.WriteLine("alpha: {0}, beta: {1}",

alpha, beta);

}

}

class PassOb {

public static void Main() {

MyClass ob1 = new MyClass(4, 5);

MyClass ob2 = new MyClass(6, 7);

Console.Write("ob1: ");

ob1.show();

Console.Write("ob2: ");

ob2.show();

if(ob1.sameAs(ob2))

Console.WriteLine("ob1 and ob2 have the same values.");

else

Console.WriteLine("ob1 and ob2 have different values.");

Console.WriteLine();

// now, make ob1 a copy of ob2

ob1.copy(ob2);

Console.Write("ob1 after copy: ");

ob1.show();

if(ob1.sameAs(ob2))

Console.WriteLine("ob1 and ob2 have the same values.");

else

Console.WriteLine("ob1 and ob2 have different values.");

}

}

listing 5

// Value types are passed by value.

using System;

class Test {

/* This method causes no change to the arguments

used in the call. */

public void noChange(int i, int j) {

i = i + j;

j = -j;

}

}

class CallByValue {

public static void Main() {

Test ob = new Test();

int a = 15, b = 20;

Console.WriteLine("a and b before call: " +

a + " " + b);

ob.noChange(a, b);

Console.WriteLine("a and b after call: " +

a + " " + b);

}

}

listing 6

// Objects are passed by reference.

using System;

class Test {

public int a, b;

public Test(int i, int j) {

a = i;

b = j;

}

/* Pass an object. Now, ob.a and ob.b in object

used in the call will be changed. */

public void change(Test ob) {

ob.a = ob.a + ob.b;

ob.b = -ob.b;

}

}

class CallByRef {

public static void Main() {

Test ob = new Test(15, 20);

Console.WriteLine("ob.a and ob.b before call: " +

ob.a + " " + ob.b);

ob.change(ob);

Console.WriteLine("ob.a and ob.b after call: " +

ob.a + " " + ob.b);

}

}

listing 7

// Use ref to pass a value type by reference.

using System;

class RefTest {

/* This method changes its argument.

Notice the use of ref. */

public void sqr(ref int i) {

i = i * i;

}

}

class RefDemo {

public static void Main() {

RefTest ob = new RefTest();

int a = 10;

Console.WriteLine("a before call: " + a);

ob.sqr(ref a); // notice the use of ref

Console.WriteLine("a after call: " + a);

}

}

listing 8

// Swap two values.

using System;

class Swap {

// This method now changes its arguments.

public void swap(ref int a, ref int b) {

int t;

t = a;

a = b;

b = t;

}

}

class SwapDemo {

public static void Main() {

Swap ob = new Swap();

int x = 10, y = 20;

Console.WriteLine("x and y before call: " + x + " " + y);

ob.swap(ref x, ref y);

Console.WriteLine("x and y after call: " + x + " " + y);

}

}

listing 9

// Use out.

using System;

class Decompose {

/* Decompose a floating-point value into its

integer and fractional parts. */

public int parts(double n, out double frac) {

int whole;

whole = (int) n;

frac = n - whole; // pass fractional part back through frac

return whole; // return integer portion

}

}

class UseOut {

public static void Main() {

Decompose ob = new Decompose();

int i;

double f;

i = ob.parts(10.125, out f);

Console.WriteLine("Integer portion is " + i);

Console.WriteLine("Fractional part is " + f);

}

}

listing 10

// Use two out parameters.

using System;

class Num {

/* Determine if x and v have a common divisor.

If so, return least and greatest common factors in

the out parameters. */

public bool hasComFactor(int x, int y,

out int least, out int greatest) {

int i;

int max = x < y ? x : y;

bool first = true;

least = 1;

greatest = 1;

// find least and greatest common factors

for(i=2; i <= max/2 + 1; i++) {

if( ((y%i)==0) & ((x%i)==0) ) {

if(first) {

least = i;

first = false;

}

greatest = i;

}

}

if(least != 1) return true;

else return false;

}

}

class DemoOut {

public static void Main() {

Num ob = new Num();

int lcf, gcf;

if(ob.hasComFactor(231, 105, out lcf, out gcf)) {

Console.WriteLine("Lcf of 231 and 105 is " + lcf);

Console.WriteLine("Gcf of 231 and 105 is " + gcf);

}

else

Console.WriteLine("No common factor for 35 and 49.");

if(ob.hasComFactor(35, 51, out lcf, out gcf)) {

Console.WriteLine("Lcf of 35 and 51 " + lcf);

Console.WriteLine("Gcf of 35 and 51 is " + gcf);

}

else

Console.WriteLine("No common factor for 35 and 51.");

}

}

listing 11

// Swap two references.

using System;

class RefSwap {

int a, b;

public RefSwap(int i, int j) {

a = i;

b = j;

}

public void show() {

Console.WriteLine("a: {0}, b: {1}", a, b);

}

// This method changes its arguments.

public void swap(ref RefSwap ob1, ref RefSwap ob2) {

RefSwap t;

t = ob1;

ob1 = ob2;

ob2 = t;

}

}

class RefSwapDemo {

public static void Main() {

RefSwap x = new RefSwap(1, 2);

RefSwap y = new RefSwap(3, 4);

Console.Write("x before call: ");

x.show();

Console.Write("y before call: ");

y.show();

Console.WriteLine();

// exchange the objects to which x and y refer

x.swap(ref x, ref y);

Console.Write("x after call: ");

x.show();

Console.Write("y after call: ");

y.show();

}

}

listing 12

// Demonstrate params.

using System;

class Min {

public int minVal(params int[] nums) {

int m;

if(nums.Length == 0) {

Console.WriteLine("Error: no arguments.");

return 0;

}

m = nums[0];

for(int i=1; i < nums.Length; i++)

if(nums[i] < m) m = nums[i];

return m;

}

}

class ParamsDemo {

public static void Main() {

Min ob = new Min();

int min;

int a = 10, b = 20;

// call with two values

min = ob.minVal(a, b);

Console.WriteLine("Minimum is " + min);

// call with 3 values

min = ob.minVal(a, b, -1);

Console.WriteLine("Minimum is " + min);

// call with 5 values

min = ob.minVal(18, 23, 3, 14, 25);

Console.WriteLine("Minimum is " + min);

// can call with an int array, too

int[] args = { 45, 67, 34, 9, 112, 8 };

min = ob.minVal(args);

Console.WriteLine("Minimum is " + min);

}

}

listing 13

// Use regular parameter with a params parameter.

using System;

class MyClass {

public void showArgs(string msg, params int[] nums) {

Console.Write(msg + ": ");

foreach(int i in nums)

Console.Write(i + " ");

Console.WriteLine();

}

}

class ParamsDemo2 {

public static void Main() {

MyClass ob = new MyClass();

ob.showArgs("Here are some integers",

1, 2, 3, 4, 5);

ob.showArgs("Here are two more",

17, 20);

}

}

listing 14

// Return an object.

using System;

class Rect {

int width;

int height;

public Rect(int w, int h) {

width = w;

height = h;

}

public int area() {

return width * height;

}

public void show() {

Console.WriteLine(width + " " + height);

}

/* Return a rectangle that is a specified

factor larger than the invoking rectangle. */

public Rect enlarge(int factor) {

return new Rect(width * factor, height * factor);

}

}

class RetObj {

public static void Main() {

Rect r1 = new Rect(4, 5);

Console.Write("Dimensions of r1: ");

r1.show();

Console.WriteLine("Area of r1: " + r1.area());

Console.WriteLine();

// create a rectangle that is twice as big as r1

Rect r2 = r1.enlarge(2);

Console.Write("Dimensions of r2: ");

r2.show();

Console.WriteLine("Area of r2 " + r2.area());

}

}

listing 15

// Use a class factory.

using System;

class MyClass {

int a, b; // private

// Create a class factory for MyClass.

public MyClass factory(int i, int j) {

MyClass t = new MyClass();

t.a = i;

t.b = j;

return t; // return an object

}

public void show() {

Console.WriteLine("a and b: " + a + " " + b);

}

}

class MakeObjects {

public static void Main() {

MyClass ob = new MyClass();

int i, j;

// generate objects using the factory

for(i=0, j=10; i < 10; i++, j--) {

MyClass anotherOb = ob.factory(i, j); // make an object

anotherOb.show();

}

Console.WriteLine();

}

}

listing 16

// Return an array.

using System;

class Factor {

/* Return an array containing the factors of num.

On return, numfactors will contain the number of

factors found. */

public int[] findfactors(int num, out int numfactors) {

int[] facts = new int[80]; // size of 80 is arbitrary

int i, j;

// find factors and put them in the facts array

for(i=2, j=0; i < num/2 + 1; i++)

if( (num%i)==0 ) {

facts[j] = i;

j++;

}

numfactors = j;

return facts;

}

}

class FindFactors {

public static void Main() {

Factor f = new Factor();

int numfactors;

int[] factors;

factors = f.findfactors(1000, out numfactors);

Console.WriteLine("Factors for 1000 are: ");

for(int i=0; i < numfactors; i++)

Console.Write(factors[i] + " ");

Console.WriteLine();

}

}

listing 17

// Demonstrate method overloading.

using System;

class Overload {

public void ovlDemo() {

Console.WriteLine("No parameters");

}

// Overload ovlDemo for one integer parameter.

public void ovlDemo(int a) {

Console.WriteLine("One parameter: " + a);

}

// Overload ovlDemo for two integer parameters.

public int ovlDemo(int a, int b) {

Console.WriteLine("Two parameters: " + a + " " + b);

return a + b;

}

// Overload ovlDemo for two double parameters.

public double ovlDemo(double a, double b) {

Console.WriteLine("Two double parameters: " +

a + " "+ b);

return a + b;

}

}

class OverloadDemo {

public static void Main() {

Overload ob = new Overload();

int resI;

double resD;

// call all versions of ovlDemo()

ob.ovlDemo();

Console.WriteLine();

ob.ovlDemo(2);

Console.WriteLine();

resI = ob.ovlDemo(4, 6);

Console.WriteLine("Result of ob.ovlDemo(4, 6): " +

resI);

Console.WriteLine();

resD = ob.ovlDemo(1.1, 2.32);

Console.WriteLine("Result of ob.ovlDemo(1.1, 2.32): " +

resD);

}

}

listing 18

/* Automatic type conversions can affect

overloaded method resolution. */

using System;

class Overload2 {

public void f(int x) {

Console.WriteLine("Inside f(int): " + x);

}

public void f(double x) {

Console.WriteLine("Inside f(double): " + x);

}

}

class TypeConv {

public static void Main() {

Overload2 ob = new Overload2();

int i = 10;

double d = 10.1;

byte b = 99;

short s = 10;

float f = 11.5F;

ob.f(i); // calls ob.f(int)

ob.f(d); // calls ob.f(double)

ob.f(b); // calls ob.f(int) -- type conversion

ob.f(s); // calls ob.f(int) -- type conversion

ob.f(f); // calls ob.f(double) -- type conversion

}

}

listing 19

// Add f(byte).

using System;

class Overload2 {

public void f(byte x) {

Console.WriteLine("Inside f(byte): " + x);

}

public void f(int x) {

Console.WriteLine("Inside f(int): " + x);

}

public void f(double x) {

Console.WriteLine("Inside f(double): " + x);

}

}

class TypeConv {

public static void Main() {

Overload2 ob = new Overload2();

int i = 10;

double d = 10.1;

byte b = 99;

short s = 10;

float f = 11.5F;

ob.f(i); // calls ob.f(int)

ob.f(d); // calls ob.f(double)

ob.f(b); // calls ob.f(byte) -- now, no type conversion

ob.f(s); // calls ob.f(int) -- type conversion

ob.f(f); // calls ob.f(double) -- type conversion

}

}

listing 20

// Demonstrate an overloaded constructor.

using System;

class MyClass {

public int x;

public MyClass() {

Console.WriteLine("Inside MyClass().");

x = 0;

}

public MyClass(int i) {

Console.WriteLine("Inside MyClass(int).");

x = i;

}

public MyClass(double d) {

Console.WriteLine("Inside MyClass(double).");

x = (int) d;

}

public MyClass(int i, int j) {

Console.WriteLine("Inside MyClass(int, int).");

x = i * j;

}

}

class OverloadConsDemo {

public static void Main() {

MyClass t1 = new MyClass();

MyClass t2 = new MyClass(88);

MyClass t3 = new MyClass(17.23);

MyClass t4 = new MyClass(2, 4);

Console.WriteLine("t1.x: " + t1.x);

Console.WriteLine("t2.x: " + t2.x);

Console.WriteLine("t3.x: " + t3.x);

Console.WriteLine("t4.x: " + t4.x);

}

}

listing 21

// A stack class for characters.

using System;

class Stack {

// these members are private

char[] stck; // holds the stack

int tos; // index of the top of the stack

// Construct an empty Stack given its size.

public Stack(int size) {

stck = new char[size]; // allocate memory for stack

tos = 0;

}

// Construct a Stack from a stack.

public Stack(Stack ob) {

// allocate memory for stack

stck = new char[ob.stck.Length];

// copy elements to new stack

for(int i=0; i < ob.tos; i++)

stck[i] = ob.stck[i];

// set tos for new stack

tos = ob.tos;

}

// Push characters onto the stack.

public void push(char ch) {

if(tos==stck.Length) {

Console.WriteLine(" -- Stack is full.");

return;

}

stck[tos] = ch;

tos++;

}

// Pop a character from the stack.

public char pop() {

if(tos==0) {

Console.WriteLine(" -- Stack is empty.");

return (char) 0;

}

tos--;

return stck[tos];

}

// Return true if the stack is full.

public bool full() {

return tos==stck.Length;

}

// Return true if the stack is empty.

public bool empty() {

return tos==0;

}

// Return total capacity of the stack.

public int capacity() {

return stck.Length;

}

// Return number of objects currently on the stack.

public int getNum() {

return tos;

}

}

// Demonstrate the Stack class.

class StackDemo {

public static void Main() {

Stack stk1 = new Stack(10);

char ch;

int i;

// Put some characters into stk1.

Console.WriteLine("Push A through J onto stk1.");

for(i=0; !stk1.full(); i++)

stk1.push((char) ('A' + i));

// Create a copy of stck1

Stack stk2 = new Stack(stk1);

// Display the contents of stk1.

Console.Write("Contents of stk1: ");

while( !stk1.empty() ) {

ch = stk1.pop();

Console.Write(ch);

}

Console.WriteLine();

Console.Write("Contents of stk2: ");

while ( !stk2.empty() ) {

ch = stk2.pop();

Console.Write(ch);

}

Console.WriteLine("\n");

}

}

listing 22

// Demonstrate invoking a constructor through this.

using System;

class XYCoord {

public int x, y;

public XYCoord() : this(0, 0) {

Console.WriteLine("Inside XYCoord()");

}

public XYCoord(XYCoord obj) : this(obj.x, obj.y) {

Console.WriteLine("Inside XYCoord(obj)");

}

public XYCoord(int i, int j) {

Console.WriteLine("Inside XYCoord(int, int)");

x = i;

y = j;

}

}

class OverloadConsDemo {

public static void Main() {

XYCoord t1 = new XYCoord();

XYCoord t2 = new XYCoord(8, 9);

XYCoord t3 = new XYCoord(t2);

Console.WriteLine("t1.x, t1.y: " + t1.x + ", " + t1.y);

Console.WriteLine("t2.x, t2.y: " + t2.x + ", " + t2.y);

Console.WriteLine("t3.x, t3.y: " + t3.x + ", " + t3.y);

}

}

listing 23

// Display all command-line information.

using System;

class CLDemo {

public static void Main(string[] args) {

Console.WriteLine("There are " + args.Length +

" command-line arguments.");

Console.WriteLine("They are: ");

for(int i=0; i < args.Length; i++)

Console.WriteLine(args[i]);

}

}

listing 24

// Encode or decode a message.

using System;

class Cipher {

public static int Main(string[] args) {

// see if arguments are present

if(args.Length < 2) {

Console.WriteLine("Usage: encode/decode word1 [word2...wordN]");

return 1; // return failure code

}

// if args present, first arg must be encode or decode

if(args[0] != "encode" & args[0] != "decode") {

Console.WriteLine("First arg must be encode or decode.");

return 1; // return failure code

}

// encode or decode message

for(int n=1; n < args.Length; n++) {

for(int i=0; i < args
.Length; i++) {

if(args[0] == "encode")

Console.Write((char) (args
[i] + 1) );

else

Console.Write((char) (args
[i] - 1) );

}

Console.Write(" ");

}

Console.WriteLine();

return 0;

}

}

listing 25

// A simple example of recursion.

using System;

class Factorial {

// This is a recursive function.

public int factR(int n) {

int result;

if(n==1) return 1;

result = factR(n-1) * n;

return result;

}

// This is an iterative equivalent.

public int factI(int n) {

int t, result;

result = 1;

for(t=1; t <= n; t++) result *= t;

return result;

}

}

class Recursion {

public static void Main() {

Factorial f = new Factorial();

Console.WriteLine("Factorials using recursive method.");

Console.WriteLine("Factorial of 3 is " + f.factR(3));

Console.WriteLine("Factorial of 4 is " + f.factR(4));

Console.WriteLine("Factorial of 5 is " + f.factR(5));

Console.WriteLine();

Console.WriteLine("Factorials using iterative method.");

Console.WriteLine("Factorial of 3 is " + f.factI(3));

Console.WriteLine("Factorial of 4 is " + f.factI(4));

Console.WriteLine("Factorial of 5 is " + f.factI(5));

}

}

listing 26

// Display a string in reverse by using recursion.

using System;

class RevStr {

// Display a string backwards.

public void displayRev(string str) {

if(str.Length > 0)

displayRev(str.Substring(1, str.Length-1));

else

return;

Console.Write(str[0]);

}

}

class RevStrDemo {

public static void Main() {

string s = "this is a test";

RevStr rsOb = new RevStr();

Console.WriteLine("Original string: " + s);

Console.Write("Reversed string: ");

rsOb.displayRev(s);

Console.WriteLine();

}

}

listing 27

// Use static.

using System;

class StaticDemo {

// a static variable

public static int val = 100;

// a static method

public static int valDiv2() {

return val/2;

}

}

class SDemo {

public static void Main() {

Console.WriteLine("Initial value of StaticDemo.val is "

+ StaticDemo.val);

StaticDemo.val = 8;

Console.WriteLine("StaticDemo.val is " + StaticDemo.val);

Console.WriteLine("StaticDemo.valDiv2(): " +

StaticDemo.valDiv2());

}

}

listing 28

class StaticError {

int denom = 3; // a normal instance variable

static int val = 1024; // a static variable

/* Error! Can't directly access a non-static variable

from within a static method. */

static int valDivDenom() {

return val/denom; // won't compile!

}

}

listing 29

using System;

class AnotherStaticError {

// non-static method.

void nonStaticMeth() {

Console.WriteLine("Inside nonStaticMeth().");

}

/* Error! Can't directly call a non-static method

from within a static method. */

static void staticMeth() {

nonStaticMeth(); // won't compile

}

}

listing 30

class MyClass {

// non-static method.

void nonStaticMeth() {

Console.WriteLine("Inside nonStaticMeth().");

}

/* Can call a non-static method through an

object reference from within a static method. */

public static void staticMeth(MyClass ob) {

ob.nonStaticMeth(); // this is OK

}

}

listing 31

// Use a static field to count instances.

using System;

class CountInst {

static int count = 0;

// increment count when object is created

public CountInst() {

count++;

}

// decrement count when object is destroyed

~CountInst() {

count--;

}

public static int getcount() {

return count;

}

}

class CountDemo {

public static void Main() {

CountInst ob;

for(int i=0; i < 10; i++) {

ob = new CountInst();

Console.WriteLine("Current count: " +

CountInst.getcount());

}

}

}

listing 32

// Use a static class factory.

using System;

class MyClass {

int a, b;

// Create a class factory for MyClass.

static public MyClass factory(int i, int j) {

MyClass t = new MyClass();

t.a = i;

t.b = j;

return t; // return an object

}

public void show() {

Console.WriteLine("a and b: " + a + " " + b);

}

}

class MakeObjects {

public static void Main() {

int i, j;

// generate objects using the factory

for(i=0, j=10; i < 10; i++, j--) {

MyClass ob = MyClass.factory(i, j); // get an object

ob.show();

}

Console.WriteLine();

}

}

listing 33

// Use a static constructor.

using System;

class Cons {

public static int alpha;

public int beta;

// static constructor

static Cons() {

alpha = 99;

Console.WriteLine("Inside static constructor.");

}

// instance constructor

public Cons() {

beta = 100;

Console.WriteLine("Inside instance constructor.");

}

}

class ConsDemo {

public static void Main() {

Cons ob = new Cons();

Console.WriteLine("Cons.alpha: " + Cons.alpha);

Console.WriteLine("ob.beta: " + ob.beta);

}

}

listing 34

// Demonstrate a static class.

using System;

static class NumericFn {

// Return the reciprocal of a value.

static public double reciprocal(double num) {

return 1/num;

}

// Return the fractional part of a value.

static public double fracPart(double num) {

return num - (int) num;

}

// Return true if num is even.

static public bool isEven(double num) {

return (num % 2) == 0 ? true : false;

}

// Return true of num is odd.

static public bool isOdd(double num) {

return !isEven(num);

}

}

class StaticClassDemo {

public static void Main() {

Console.WriteLine("Reciprocal of 5 is " +

NumericFn.reciprocal(5.0));

Console.WriteLine("Fractional part of 4.234 is " +

NumericFn.fracPart(4.234));

if(NumericFn.isEven(10))

Console.WriteLine("10 is even.");

if(NumericFn.isOdd(5))

Console.WriteLine("5 is odd.");

// The following attempt to create an instance of

// NumericFn will cause an error.

// NumericFn ob = new NumericFn(); // Wrong!

}

}

listing 1

// An example of operator overloading.

using System;

// A three-dimensional coordinate class.

class ThreeD {

int x, y, z; // 3-D coordinates

public ThreeD() { x = y = z = 0; }

public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// Overload binary +.

public static ThreeD operator +(ThreeD op1, ThreeD op2)

{

ThreeD result = new ThreeD();

/* This adds together the coordinates of the two points

and returns the result. */

result.x = op1.x + op2.x; // These are integer additions

result.y = op1.y + op2.y; // and the + retains its original

result.z = op1.z + op2.z; // meaning relative to them.

return result;

}

// Overload binary -.

public static ThreeD operator -(ThreeD op1, ThreeD op2)

{

ThreeD result = new ThreeD();

/* Notice the order of the operands. op1 is the left

operand and op2 is the right. */

result.x = op1.x - op2.x; // these are integer subtractions

result.y = op1.y - op2.y;

result.z = op1.z - op2.z;

return result;

}

// Show X, Y, Z coordinates.

public void show()

{

Console.WriteLine(x + ", " + y + ", " + z);

}

}

class ThreeDDemo {

public static void Main() {

ThreeD a = new ThreeD(1, 2, 3);

ThreeD b = new ThreeD(10, 10, 10);

ThreeD c = new ThreeD();

Console.Write("Here is a: ");

a.show();

Console.WriteLine();

Console.Write("Here is b: ");

b.show();

Console.WriteLine();

c = a + b; // add a and b together

Console.Write("Result of a + b: ");

c.show();

Console.WriteLine();

c = a + b + c; // add a, b and c together

Console.Write("Result of a + b + c: ");

c.show();

Console.WriteLine();

c = c - a; // subtract a

Console.Write("Result of c - a: ");

c.show();

Console.WriteLine();

c = c - b; // subtract b

Console.Write("Result of c - b: ");

c.show();

Console.WriteLine();

}

}

listing 2

// More operator overloading.

using System;

// A three-dimensional coordinate class.

class ThreeD {

int x, y, z; // 3-D coordinates

public ThreeD() { x = y = z = 0; }

public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// Overload binary +.

public static ThreeD operator +(ThreeD op1, ThreeD op2)

{

ThreeD result = new ThreeD();

/* This adds together the coordinates of the two points

and returns the result. */

result.x = op1.x + op2.x;

result.y = op1.y + op2.y;

result.z = op1.z + op2.z;

return result;

}

// Overload binary -.

public static ThreeD operator -(ThreeD op1, ThreeD op2)

{

ThreeD result = new ThreeD();

/* Notice the order of the operands. op1 is the left

operand and op2 is the right. */

result.x = op1.x - op2.x;

result.y = op1.y - op2.y;

result.z = op1.z - op2.z;

return result;

}

// Overload unary -.

public static ThreeD operator -(ThreeD op)

{

ThreeD result = new ThreeD();

result.x = -op.x;

result.y = -op.y;

result.z = -op.z;

return result;

}

// Overload unary ++.

public static ThreeD operator ++(ThreeD op)

{

// for ++, modify argument

op.x++;

op.y++;

op.z++;

return op;

}

// Show X, Y, Z coordinates.

public void show()

{

Console.WriteLine(x + ", " + y + ", " + z);

}

}

class ThreeDDemo {

public static void Main() {

ThreeD a = new ThreeD(1, 2, 3);

ThreeD b = new ThreeD(10, 10, 10);

ThreeD c = new ThreeD();

Console.Write("Here is a: ");

a.show();

Console.WriteLine();

Console.Write("Here is b: ");

b.show();

Console.WriteLine();

c = a + b; // add a and b together

Console.Write("Result of a + b: ");

c.show();

Console.WriteLine();

c = a + b + c; // add a, b and c together

Console.Write("Result of a + b + c: ");

c.show();

Console.WriteLine();

c = c - a; // subtract a

Console.Write("Result of c - a: ");

c.show();

Console.WriteLine();

c = c - b; // subtract b

Console.Write("Result of c - b: ");

c.show();

Console.WriteLine();

c = -a; // assign -a to c

Console.Write("Result of -a: ");

c.show();

Console.WriteLine();

a++; // increment a

Console.Write("Result of a++: ");

a.show();

}

}

listing 3

/* Overload addition for object + object, and

for object + int. */

using System;

// A three-dimensional coordinate class.

class ThreeD {

int x, y, z; // 3-D coordinates

public ThreeD() { x = y = z = 0; }

public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// Overload binary + for object + object.

public static ThreeD operator +(ThreeD op1, ThreeD op2)

{

ThreeD result = new ThreeD();

/* This adds together the coordinates of the two points

and returns the result. */

result.x = op1.x + op2.x;

result.y = op1.y + op2.y;

result.z = op1.z + op2.z;

return result;

}

// Overload binary + for object + int.

public static ThreeD operator +(ThreeD op1, int op2)

{

ThreeD result = new ThreeD();

result.x = op1.x + op2;

result.y = op1.y + op2;

result.z = op1.z + op2;

return result;

}

// Show X, Y, Z coordinates.

public void show()

{

Console.WriteLine(x + ", " + y + ", " + z);

}

}

class ThreeDDemo {

public static void Main() {

ThreeD a = new ThreeD(1, 2, 3);

ThreeD b = new ThreeD(10, 10, 10);

ThreeD c = new ThreeD();

Console.Write("Here is a: ");

a.show();

Console.WriteLine();

Console.Write("Here is b: ");

b.show();

Console.WriteLine();

c = a + b; // object + object

Console.Write("Result of a + b: ");

c.show();

Console.WriteLine();

c = b + 10; // object + int

Console.Write("Result of b + 10: ");

c.show();

}

}

listing 4

/* Overload the + for object + object,

object + int, and int + object. */

using System;

// A three-dimensional coordinate class.

class ThreeD {

int x, y, z; // 3-D coordinates

public ThreeD() { x = y = z = 0; }

public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// Overload binary + for object + object.

public static ThreeD operator +(ThreeD op1, ThreeD op2)

{

ThreeD result = new ThreeD();

/* This adds together the coordinates of the two points

and returns the result. */

result.x = op1.x + op2.x;

result.y = op1.y + op2.y;

result.z = op1.z + op2.z;

return result;

}

// Overload binary + for object + int.

public static ThreeD operator +(ThreeD op1, int op2)

{

ThreeD result = new ThreeD();

result.x = op1.x + op2;

result.y = op1.y + op2;

result.z = op1.z + op2;

return result;

}

// Overload binary + for int + object.

public static ThreeD operator +(int op1, ThreeD op2)

{

ThreeD result = new ThreeD();

result.x = op2.x + op1;

result.y = op2.y + op1;

result.z = op2.z + op1;

return result;

}

// Show X, Y, Z coordinates.

public void show()

{

Console.WriteLine(x + ", " + y + ", " + z);

}

}

class ThreeDDemo {

public static void Main() {

ThreeD a = new ThreeD(1, 2, 3);

ThreeD b = new ThreeD(10, 10, 10);

ThreeD c = new ThreeD();

Console.Write("Here is a: ");

a.show();

Console.WriteLine();

Console.Write("Here is b: ");

b.show();

Console.WriteLine();

c = a + b; // object + object

Console.Write("Result of a + b: ");

c.show();

Console.WriteLine();

c = b + 10; // object + int

Console.Write("Result of b + 10: ");

c.show();

Console.WriteLine();

c = 15 + b; // int + object

Console.Write("Result of 15 + b: ");

c.show();

}

}

listing 5

// Overload < and >.

using System;

// A three-dimensional coordinate class.

class ThreeD {

int x, y, z; // 3-D coordinates

public ThreeD() { x = y = z = 0; }

public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// Overload <.

public static bool operator <(ThreeD op1, ThreeD op2)

{

if((op1.x < op2.x) && (op1.y < op2.y) && (op1.z < op2.z))

return true;

else

return false;

}

// Overload >.

public static bool operator >(ThreeD op1, ThreeD op2)

{

if((op1.x > op2.x) && (op1.y > op2.y) && (op1.z > op2.z))

return true;

else

return false;

}

// Show X, Y, Z coordinates.

public void show()

{

Console.WriteLine(x + ", " + y + ", " + z);

}

}

class ThreeDDemo {

public static void Main() {

ThreeD a = new ThreeD(5, 6, 7);

ThreeD b = new ThreeD(10, 10, 10);

ThreeD c = new ThreeD(1, 2, 3);

Console.Write("Here is a: ");

a.show();

Console.Write("Here is b: ");

b.show();

Console.Write("Here is c: ");

c.show();

Console.WriteLine();

if(a > c) Console.WriteLine("a > c is true");

if(a < c) Console.WriteLine("a < c is true");

if(a > b) Console.WriteLine("a > b is true");

if(a < b) Console.WriteLine("a < b is true");

}

}

listing 6

// Overload true and false for ThreeD.

using System;

// A three-dimensional coordinate class.

class ThreeD {

int x, y, z; // 3-D coordinates

public ThreeD() { x = y = z = 0; }

public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// Overload true.

public static bool operator true(ThreeD op) {

if((op.x != 0) || (op.y != 0) || (op.z != 0))

return true; // at least one coordinate is non-zero

else

return false;

}

// Overload false.

public static bool operator false(ThreeD op) {

if((op.x == 0) && (op.y == 0) && (op.z == 0))

return true; // all coordinates are zero

else

return false;

}

// Overload unary --.

public static ThreeD operator --(ThreeD op)

{

// for ++, modify argument

op.x--;

op.y--;

op.z--;

return op;

}

// Show X, Y, Z coordinates.

public void show()

{

Console.WriteLine(x + ", " + y + ", " + z);

}

}

class TrueFalseDemo {

public static void Main() {

ThreeD a = new ThreeD(5, 6, 7);

ThreeD b = new ThreeD(10, 10, 10);

ThreeD c = new ThreeD(0, 0, 0);

Console.Write("Here is a: ");

a.show();

Console.Write("Here is b: ");

b.show();

Console.Write("Here is c: ");

c.show();

Console.WriteLine();

if(a) Console.WriteLine("a is true.");

else Console.WriteLine("a is false.");

if(b) Console.WriteLine("b is true.");

else Console.WriteLine("b is false.");

if(c) Console.WriteLine("c is true.");

else Console.WriteLine("c is false.");

Console.WriteLine();

Console.WriteLine("Control a loop using a ThreeD object.");

do {

b.show();

b--;

} while(b);

}

}

listing 7

// A simple way to overload !, |, and & for ThreeD.

using System;

// A three-dimensional coordinate class.

class ThreeD {

int x, y, z; // 3-D coordinates

public ThreeD() { x = y = z = 0; }

public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// Overload |.

public static bool operator |(ThreeD op1, ThreeD op2)

{

if( ((op1.x != 0) || (op1.y != 0) || (op1.z != 0)) |

((op2.x != 0) || (op2.y != 0) || (op2.z != 0)) )

return true;

else

return false;

}

// Overload &.

public static bool operator &(ThreeD op1, ThreeD op2)

{

if( ((op1.x != 0) && (op1.y != 0) && (op1.z != 0)) &

((op2.x != 0) && (op2.y != 0) && (op2.z != 0)) )

return true;

else

return false;

}

// Overload !.

public static bool operator !(ThreeD op)

{

if((op.x != 0) || (op.y != 0) || (op.z != 0))

return false;

else return true;

}

// Show X, Y, Z coordinates.

public void show()

{

Console.WriteLine(x + ", " + y + ", " + z);

}

}

class TrueFalseDemo {

public static void Main() {

ThreeD a = new ThreeD(5, 6, 7);

ThreeD b = new ThreeD(10, 10, 10);

ThreeD c = new ThreeD(0, 0, 0);

Console.Write("Here is a: ");

a.show();

Console.Write("Here is b: ");

b.show();

Console.Write("Here is c: ");

c.show();

Console.WriteLine();

if(!a) Console.WriteLine("a is false.");

if(!b) Console.WriteLine("b is false.");

if(!c) Console.WriteLine("c is false.");

Console.WriteLine();

if(a & b) Console.WriteLine("a & b is true.");

else Console.WriteLine("a & b is false.");

if(a & c) Console.WriteLine("a & c is true.");

else Console.WriteLine("a & c is false.");

if(a | b) Console.WriteLine("a | b is true.");

else Console.WriteLine("a | b is false.");

if(a | c) Console.WriteLine("a | c is true.");

else Console.WriteLine("a | c is false.");

}

}

listing 8

/* A better way to overload !, |, and & for ThreeD.

This version automatically enables the && and || operators. */

using System;

// A three-dimensional coordinate class.

class ThreeD {

int x, y, z; // 3-D coordinates

public ThreeD() { x = y = z = 0; }

public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// Overload | for short-circuit evaluation.

public static ThreeD operator |(ThreeD op1, ThreeD op2)

{

if( ((op1.x != 0) || (op1.y != 0) || (op1.z != 0)) |

((op2.x != 0) || (op2.y != 0) || (op2.z != 0)) )

return new ThreeD(1, 1, 1);

else

return new ThreeD(0, 0, 0);

}

// Overload & for short-circuit evaluation.

public static ThreeD operator &(ThreeD op1, ThreeD op2)

{

if( ((op1.x != 0) && (op1.y != 0) && (op1.z != 0)) &

((op2.x != 0) && (op2.y != 0) && (op2.z != 0)) )

return new ThreeD(1, 1, 1);

else

return new ThreeD(0, 0, 0);

}

// Overload !.

public static bool operator !(ThreeD op)

{

if(op) return false;

else return true;

}

// Overload true.

public static bool operator true(ThreeD op) {

if((op.x != 0) || (op.y != 0) || (op.z != 0))

return true; // at least one coordinate is non-zero

else

return false;

}

// Overload false.

public static bool operator false(ThreeD op) {

if((op.x == 0) && (op.y == 0) && (op.z == 0))

return true; // all coordinates are zero

else

return false;

}

// Show X, Y, Z coordinates.

public void show()

{

Console.WriteLine(x + ", " + y + ", " + z);

}

}

class TrueFalseDemo {

public static void Main() {

ThreeD a = new ThreeD(5, 6, 7);

ThreeD b = new ThreeD(10, 10, 10);

ThreeD c = new ThreeD(0, 0, 0);

Console.Write("Here is a: ");

a.show();

Console.Write("Here is b: ");

b.show();

Console.Write("Here is c: ");

c.show();

Console.WriteLine();

if(a) Console.WriteLine("a is true.");

if(b) Console.WriteLine("b is true.");

if(c) Console.WriteLine("c is true.");

if(!a) Console.WriteLine("a is false.");

if(!b) Console.WriteLine("b is false.");

if(!c) Console.WriteLine("c is false.");

Console.WriteLine();

Console.WriteLine("Use & and |");

if(a & b) Console.WriteLine("a & b is true.");

else Console.WriteLine("a & b is false.");

if(a & c) Console.WriteLine("a & c is true.");

else Console.WriteLine("a & c is false.");

if(a | b) Console.WriteLine("a | b is true.");

else Console.WriteLine("a | b is false.");

if(a | c) Console.WriteLine("a | c is true.");

else Console.WriteLine("a | c is false.");

Console.WriteLine();

// now use short-circuit ops

Console.WriteLine("Use short-circuit && and ||");

if(a && b) Console.WriteLine("a && b is true.");

else Console.WriteLine("a && b is false.");

if(a && c) Console.WriteLine("a && c is true.");

else Console.WriteLine("a && c is false.");

if(a || b) Console.WriteLine("a || b is true.");

else Console.WriteLine("a || b is false.");

if(a || c) Console.WriteLine("a || c is true.");

else Console.WriteLine("a || c is false.");

}

}

listing 9

// An example that uses an implicit conversion operator.

using System;

// A three-dimensional coordinate class.

class ThreeD {

int x, y, z; // 3-D coordinates

public ThreeD() { x = y = z = 0; }

public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// Overload binary +.

public static ThreeD operator +(ThreeD op1, ThreeD op2)

{

ThreeD result = new ThreeD();

result.x = op1.x + op2.x;

result.y = op1.y + op2.y;

result.z = op1.z + op2.z;

return result;

}

// An implicit conversion from ThreeD to int.

public static implicit operator int(ThreeD op1)

{

return op1.x * op1.y * op1.z;

}

// Show X, Y, Z coordinates.

public void show()

{

Console.WriteLine(x + ", " + y + ", " + z);

}

}

class ThreeDDemo {

public static void Main() {

ThreeD a = new ThreeD(1, 2, 3);

ThreeD b = new ThreeD(10, 10, 10);

ThreeD c = new ThreeD();

int i;

Console.Write("Here is a: ");

a.show();

Console.WriteLine();

Console.Write("Here is b: ");

b.show();

Console.WriteLine();

c = a + b; // add a and b together

Console.Write("Result of a + b: ");

c.show();

Console.WriteLine();

i = a; // convert to int

Console.WriteLine("Result of i = a: " + i);

Console.WriteLine();

i = a * 2 - b; // convert to int

Console.WriteLine("result of a * 2 - b: " + i);

}

}

listing 10

// Use an explicit conversion.

using System;

// A three-dimensional coordinate class.

class ThreeD {

int x, y, z; // 3-D coordinates

public ThreeD() { x = y = z = 0; }

public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// Overload binary +.

public static ThreeD operator +(ThreeD op1, ThreeD op2)

{

ThreeD result = new ThreeD();

result.x = op1.x + op2.x;

result.y = op1.y + op2.y;

result.z = op1.z + op2.z;

return result;

}

// This is now explicit.

public static explicit operator int(ThreeD op1)

{

return op1.x * op1.y * op1.z;

}

// Show X, Y, Z coordinates.

public void show()

{

Console.WriteLine(x + ", " + y + ", " + z);

}

}

class ThreeDDemo {

public static void Main() {

ThreeD a = new ThreeD(1, 2, 3);

ThreeD b = new ThreeD(10, 10, 10);

ThreeD c = new ThreeD();

int i;

Console.Write("Here is a: ");

a.show();

Console.WriteLine();

Console.Write("Here is b: ");

b.show();

Console.WriteLine();

c = a + b; // add a and b together

Console.Write("Result of a + b: ");

c.show();

Console.WriteLine();

i = (int) a; // explicitly convert to int -- cast required

Console.WriteLine("Result of i = a: " + i);

Console.WriteLine();

i = (int)a * 2 - (int)b; // casts required

Console.WriteLine("result of a * 2 - b: " + i);

}

}

listing 11

// Create a 4-bit type called Nybble.

using System;

// A 4-bit type.

class Nybble {

int val; // underlying storage

public Nybble() { val = 0; }

public Nybble(int i) {

val = i;

val = val & 0xF; // retain lower 4 bits

}

// Overload binary + for Nybble + Nybble.

public static Nybble operator +(Nybble op1, Nybble op2)

{

Nybble result = new Nybble();

result.val = op1.val + op2.val;

result.val = result.val & 0xF; // retain lower 4 bits

return result;

}

// Overload binary + for Nybble + int.

public static Nybble operator +(Nybble op1, int op2)

{

Nybble result = new Nybble();

result.val = op1.val + op2;

result.val = result.val & 0xF; // retain lower 4 bits

return result;

}

// Overload binary + for int + Nybble.

public static Nybble operator +(int op1, Nybble op2)

{

Nybble result = new Nybble();

result.val = op1 + op2.val;

result.val = result.val & 0xF; // retain lower 4 bits

return result;

}

// Overload ++.

public static Nybble operator ++(Nybble op)

{

op.val++;

op.val = op.val & 0xF; // retain lower 4 bits

return op;

}

// Overload >.

public static bool operator >(Nybble op1, Nybble op2)

{

if(op1.val > op2.val) return true;

else return false;

}

// Overload <.

public static bool operator <(Nybble op1, Nybble op2)

{

if(op1.val < op2.val) return true;

else return false;

}

// Convert a Nybble into an int.

public static implicit operator int (Nybble op)

{

return op.val;

}

// Convert an int into a Nybble.

public static implicit operator Nybble (int op)

{

return new Nybble(op);

}

}

class NybbleDemo {

public static void Main() {

Nybble a = new Nybble(1);

Nybble b = new Nybble(10);

Nybble c = new Nybble();

int t;

Console.WriteLine("a: " + (int) a);

Console.WriteLine("b: " + (int) b);

// use a Nybble in an if statement

if(a < b) Console.WriteLine("a is less than b\n");

// Add two Nybbles together

c = a + b;

Console.WriteLine("c after c = a + b: " + (int) c);

// Add an int to a Nybble

a += 5;

Console.WriteLine("a after a += 5: " + (int) a);

Console.WriteLine();

// use a Nybble in an int expression

t = a * 2 + 3;

Console.WriteLine("Result of a * 2 + 3: " + t);

Console.WriteLine();

// illustrate int assignment and overflow

a = 19;

Console.WriteLine("Result of a = 19: " + (int) a);

Console.WriteLine();

// use a Nybble to control a loop

Console.WriteLine("Control a for loop with a Nybble.");

for(a = 0; a < 10; a++)

Console.Write((int) a + " ");

Console.WriteLine();

}

}

listing 1

// Use an indexer to create a fail-soft array.

using System;

class FailSoftArray {

int[] a; // reference to underlying array

public int Length; // Length is public

public bool errflag; // indicates outcome of last operation

// Construct array given its size.

public FailSoftArray(int size) {

a = new int[size];

Length = size;

}

// This is the indexer for FailSoftArray.

public int this[int index] {

// This is the get accessor.

get {

if(ok(index)) {

errflag = false;

return a[index];

} else {

errflag = true;

return 0;

}

}

// This is the set accessor

set {

if(ok(index)) {

a[index] = value;

errflag = false;

}

else errflag = true;

}

}

// Return true if index is within bounds.

private bool ok(int index) {

if(index >= 0 & index < Length) return true;

return false;

}

}

// Demonstrate the fail-soft array.

class FSDemo {

public static void Main() {

FailSoftArray fs = new FailSoftArray(5);

int x;

// show quiet failures

Console.WriteLine("Fail quietly.");

for(int i=0; i < (fs.Length * 2); i++)

fs[i] = i*10;

for(int i=0; i < (fs.Length * 2); i++) {

x = fs[i];

if(x != -1) Console.Write(x + " ");

}

Console.WriteLine();

// now, generate failures

Console.WriteLine("\nFail with error reports.");

for(int i=0; i < (fs.Length * 2); i++) {

fs[i] = i*10;

if(fs.errflag)

Console.WriteLine("fs[" + i + "] out-of-bounds");

}

for(int i=0; i < (fs.Length * 2); i++) {

x = fs[i];

if(!fs.errflag) Console.Write(x + " ");

else

Console.WriteLine("fs[" + i + "] out-of-bounds");

}

}

}

listing 2

// Overload the FailSoftArray indexer.

using System;

class FailSoftArray {

int[] a; // reference to underlying array

public int Length; // Length is public

public bool errflag; // indicates outcome of last operation

// Construct array given its size.

public FailSoftArray(int size) {

a = new int[size];

Length = size;

}

// This is the int indexer for FailSoftArray.

public int this[int index] {

// This is the get accessor.

get {

if(ok(index)) {

errflag = false;

return a[index];

} else {

errflag = true;

return 0;

}

}

// This is the set accessor

set {

if(ok(index)) {

a[index] = value;

errflag = false;

}

else errflag = true;

}

}

/* This is another indexer for FailSoftArray.

This index takes a double argument. It then

rounds that argument to the nearest integer

index. */

public int this[double idx] {

// This is the get accessor.

get {

int index;

// round to nearest int

if( (idx - (int) idx) < 0.5) index = (int) idx;

else index = (int) idx + 1;

if(ok(index)) {

errflag = false;

return a[index];

} else {

errflag = true;

return 0;

}

}

// This is the set accessor

set {

int index;

// round to nearest int

if( (idx - (int) idx) < 0.5) index = (int) idx;

else index = (int) idx + 1;

if(ok(index)) {

a[index] = value;

errflag = false;

}

else errflag = true;

}

}

// Return true if index is within bounds.

private bool ok(int index) {

if(index >= 0 & index < Length) return true;

return false;

}

}

// Demonstrate the fail-soft array.

class FSDemo {

public static void Main() {

FailSoftArray fs = new FailSoftArray(5);

// put some values in fs

for(int i=0; i < fs.Length; i++)

fs[i] = i;

// now index with ints and doubles

Console.WriteLine("fs[1]: " + fs[1]);

Console.WriteLine("fs[2]: " + fs[2]);

Console.WriteLine("fs[1.1]: " + fs[1.1]);

Console.WriteLine("fs[1.6]: " + fs[1.6]);

}

}

listing 3

// Indexers don't have to operate on actual arrays.

using System;

class PwrOfTwo {

/* Access a logical array that contains

the powers of 2 from 0 to 15. */

public int this[int index] {

// Compute and return power of 2.

get {

if((index >= 0) && (index < 16)) return pwr(index);

else return -1;

}

// there is no set accessor

}

int pwr(int p) {

int result = 1;

for(int i=0; i < p; i++)

result *= 2;

return result;

}

}

class UsePwrOfTwo {

public static void Main() {

PwrOfTwo pwr = new PwrOfTwo();

Console.Write("First 8 powers of 2: ");

for(int i=0; i < 8; i++)

Console.Write(pwr[i] + " ");

Console.WriteLine();

Console.Write("Here are some errors: ");

Console.Write(pwr[-1] + " " + pwr[17]);

Console.WriteLine();

}

}

listing 4

// A two-dimensional fail-soft array.

using System;

class FailSoftArray2D {

int[,] a; // reference to underlying 2D array

int rows, cols; // dimensions

public int Length; // Length is public

public bool errflag; // indicates outcome of last operation

// Construct array given its dimensions.

public FailSoftArray2D(int r, int c) {

rows = r;

cols = c;

a = new int[rows, cols];

Length = rows * cols;

}

// This is the indexer for FailSoftArray2D.

public int this[int index1, int index2] {

// This is the get accessor.

get {

if(ok(index1, index2)) {

errflag = false;

return a[index1, index2];

} else {

errflag = true;

return 0;

}

}

// This is the set accessor.

set {

if(ok(index1, index2)) {

a[index1, index2] = value;

errflag = false;

}

else errflag = true;

}

}

// Return true if indexes are within bounds.

private bool ok(int index1, int index2) {

if(index1 >= 0 & index1 < rows &

index2 >= 0 & index2 < cols)

return true;

return false;

}

}

// Demonstrate a 2D indexer.

class TwoDIndexerDemo {

public static void Main() {

FailSoftArray2D fs = new FailSoftArray2D(3, 5);

int x;

// show quiet failures

Console.WriteLine("Fail quietly.");

for(int i=0; i < 6; i++)

fs[i, i] = i*10;

for(int i=0; i < 6; i++) {

x = fs[i,i];

if(x != -1) Console.Write(x + " ");

}

Console.WriteLine();

// now, generate failures

Console.WriteLine("\nFail with error reports.");

for(int i=0; i < 6; i++) {

fs[i,i] = i*10;

if(fs.errflag)

Console.WriteLine("fs[" + i + ", " + i + "] out-of-bounds");

}

for(int i=0; i < 6; i++) {

x = fs[i,i];

if(!fs.errflag) Console.Write(x + " ");

else

Console.WriteLine("fs[" + i + ", " + i + "] out-of-bounds");

}

}

}

listing 5

// A simple property example.

using System;

class SimpProp {

int prop; // field being managed by MyProp

public SimpProp() { prop = 0; }

/* This is the property that supports access to

the private instance variable prop. It

allows only positive values. */

public int MyProp {

get {

return prop;

}

set {

if(value >= 0) prop = value;

}

}

}

// Demonstrate a property.

class PropertyDemo {

public static void Main() {

SimpProp ob = new SimpProp();

Console.WriteLine("Original value of ob.MyProp: " + ob.MyProp);

ob.MyProp = 100; // assign value

Console.WriteLine("Value of ob.MyProp: " + ob.MyProp);

// Can't assign negative value to prop

Console.WriteLine("Attempting to assign -10 to ob.MyProp");

ob.MyProp = -10;

Console.WriteLine("Value of ob.MyProp: " + ob.MyProp);

}

}

listing 6

// Add Length property to FailSoftArray.

using System;

class FailSoftArray {

int[] a; // reference to underlying array

int len; // length of array -- underlies Length property

public bool errflag; // indicates outcome of last operation

// Construct array given its size.

public FailSoftArray(int size) {

a = new int[size];

len = size;

}

// Read-only Length property.

public int Length {

get {

return len;

}

}

// This is the indexer for FailSoftArray.

public int this[int index] {

// This is the get accessor.

get {

if(ok(index)) {

errflag = false;

return a[index];

} else {

errflag = true;

return 0;

}

}

// This is the set accessor

set {

if(ok(index)) {

a[index] = value;

errflag = false;

}

else errflag = true;

}

}

// Return true if index is within bounds.

private bool ok(int index) {

if(index >= 0 & index < Length) return true;

return false;

}

}

// Demonstrate the improved fail-soft array.

class ImprovedFSDemo {

public static void Main() {

FailSoftArray fs = new FailSoftArray(5);

int x;

// can read Length

for(int i=0; i < fs.Length; i++)

fs[i] = i*10;

for(int i=0; i < fs.Length; i++) {

x = fs[i];

if(x != -1) Console.Write(x + " ");

}

Console.WriteLine();

// fs.Length = 10; // Error, illegal!

}

}

listing 7

// Convert errflag into a property.

using System;

class FailSoftArray {

int[] a; // reference to underlying array

int len; // length of array

bool errflag; // now private

// Construct array given its size.

public FailSoftArray(int size) {

a = new int[size];

len = size;

}

// Read-only Length property.

public int Length {

get {

return len;

}

}

// Read-only Error property.

public bool Error {

get {

return errflag;

}

}

// This is the indexer for FailSoftArray.

public int this[int index] {

// This is the get accessor.

get {

if(ok(index)) {

errflag = false;

return a[index];

} else {

errflag = true;

return 0;

}

}

// This is the set accessor

set {

if(ok(index)) {

a[index] = value;

errflag = false;

}

else errflag = true;

}

}

// Return true if index is within bounds.

private bool ok(int index) {

if(index >= 0 & index < Length) return true;

return false;

}

}

// Demonstrate the improved fail-soft array.

class FinalFSDemo {

public static void Main() {

FailSoftArray fs = new FailSoftArray(5);

// use Error property

for(int i=0; i < fs.Length + 1; i++) {

fs[i] = i*10;

if(fs.Error)

Console.WriteLine("Error with index " + i);

}

}

}

listing 8

// Use an access modifier with an accessor.

using System;

class PropAccess {

int prop; // field being managed by MyProp

public PropAccess() { prop = 0; }

/* This is the property that supports access to

the private instance variable prop. It allows

any code to obtain the value of prop, but

only other class members can set the value

of prop. */

public int MyProp {

get {

return prop;

}

private set { // now, private

prop = value;

}

}

// This class member increments the value of MyProp.

public void incrProp() {

MyProp++; // OK, in same class.

}

}

// Demonstrate accessor access modifier.

class PropAccessDemo {

public static void Main() {

PropAccess ob = new PropAccess();

Console.WriteLine("Original value of ob.MyProp: " + ob.MyProp);

// ob.MyProp = 100; // can't access set

ob.incrProp();

Console.WriteLine("Value of ob.MyProp after increment: "

+ ob.MyProp);

}

}

listing 9

/* Create a specifiable range array class.

The RangeArray class allows indexing

to begin at some value other than zero.

When you create a RangeArray, you specify

the beginning and ending index. Negative

indexes are also allowed. For example,

you can create arrays that index from -5 to 5,

1 to 10, or 50 to 56.

*/

using System;

class RangeArray {

// private data

int[] a; // reference to underlying array

int lowerBound; // lowest index

int upperBound; // greatest index

// data for properties

int len; // underlying var for Length property

bool errflag; // underlying var for outcome

// Construct array given its size.

public RangeArray(int low, int high) {

high++;

if(high <= low) {

Console.WriteLine("Invalid Indices");

high = 1; // create a minimal array for safety

low = 0;

}

a = new int[high - low];

len = high - low;

lowerBound = low;

upperBound = --high;

}

// Read-only Length property.

public int Length {

get {

return len;

}

}

// Read-only Error property.

public bool Error {

get {

return errflag;

}

}

// This is the indexer for RangeArray.

public int this[int index] {

// This is the get accessor.

get {

if(ok(index)) {

errflag = false;

return a[index - lowerBound];

} else {

errflag = true;

return 0;

}

}

// This is the set accessor

set {

if(ok(index)) {

a[index - lowerBound] = value;

errflag = false;

}

else errflag = true;

}

}

// Return true if index is within bounds.

private bool ok(int index) {

if(index >= lowerBound & index <= upperBound) return true;

return false;

}

}

// Demonstrate the index-range array.

class RangeArrayDemo {

public static void Main() {

RangeArray ra = new RangeArray(-5, 5);

RangeArray ra2 = new RangeArray(1, 10);

RangeArray ra3 = new RangeArray(-20, -12);

// Demonstrate ra

Console.WriteLine("Length of ra: " + ra.Length);

for(int i = -5; i <= 5; i++)

ra[i] = i;

Console.Write("Contents of ra: ");

for(int i = -5; i <= 5; i++)

Console.Write(ra[i] + " ");

Console.WriteLine("\n");

// Demonstrate ra2

Console.WriteLine("Length of ra2: " + ra2.Length);

for(int i = 1; i <= 10; i++)

ra2[i] = i;

Console.Write("Contents of ra2: ");

for(int i = 1; i <= 10; i++)

Console.Write(ra2[i] + " ");

Console.WriteLine("\n");

// Demonstrate ra3

Console.WriteLine("Length of ra3: " + ra3.Length);

for(int i = -20; i <= -12; i++)

ra3[i] = i;

Console.Write("Contents of ra3: ");

for(int i = -20; i <= -12; i++)

Console.Write(ra3[i] + " ");

Console.WriteLine("\n");

}

}

listing 1

// A simple class hierarchy.

using System;

// A class for two-dimensional objects.

class TwoDShape {

public double width;

public double height;

public void showDim() {

Console.WriteLine("Width and height are " +

width + " and " + height);

}

}

// Triangle is derived from TwoDShape.

class Triangle : TwoDShape {

public string style; // style of triangle

// Return area of triangle.

public double area() {

return width * height / 2;

}

// Display a triangle's style.

public void showStyle() {

Console.WriteLine("Triangle is " + style);

}

}

class Shapes {

public static void Main() {

Triangle t1 = new Triangle();

Triangle t2 = new Triangle();

t1.width = 4.0;

t1.height = 4.0;

t1.style = "isosceles";

t2.width = 8.0;

t2.height = 12.0;

t2.style = "right";

Console.WriteLine("Info for t1: ");

t1.showStyle();

t1.showDim();

Console.WriteLine("Area is " + t1.area());

Console.WriteLine();

Console.WriteLine("Info for t2: ");

t2.showStyle();

t2.showDim();

Console.WriteLine("Area is " + t2.area());

}

}

listing 2

// Private members are not inherited.

// This example will not compile.

using System;

// A class for two-dimensional objects.

class TwoDShape {

double width; // now private

double height; // now private

public void showDim() {

Console.WriteLine("Width and height are " +

width + " and " + height);

}

}

// Triangle is derived from TwoDShape.

class Triangle : TwoDShape {

public string style; // style of triangle

// Return area of triangle.

public double area() {

return width * height / 2; // Error, can't access private member

}

// Display a triangle's style.

public void showStyle() {

Console.WriteLine("Triangle is " + style);

}

}

listing 3

// Use properties to set and get private members.

using System;

// A class for two-dimensional objects.

class TwoDShape {

double pri_width; // now private

double pri_height; // now private

// Properties for width and height.

public double width {

get { return pri_width; }

set { pri_width = value; }

}

public double height {

get { return pri_height; }

set { pri_height = value; }

}

public void showDim() {

Console.WriteLine("Width and height are " +

width + " and " + height);

}

}

// A derived class of TwoDShape for triangles.

class Triangle : TwoDShape {

public string style; // style of triangle

// Return area of triangle.

public double area() {

return width * height / 2;

}

// Display a triangle's style.

public void showStyle() {

Console.WriteLine("Triangle is " + style);

}

}

class Shapes2 {

public static void Main() {

Triangle t1 = new Triangle();

Triangle t2 = new Triangle();

t1.width = 4.0;

t1.height = 4.0;

t1.style = "isosceles";

t2.width = 8.0;

t2.height = 12.0;

t2.style = "right";

Console.WriteLine("Info for t1: ");

t1.showStyle();

t1.showDim();

Console.WriteLine("Area is " + t1.area());

Console.WriteLine();

Console.WriteLine("Info for t2: ");

t2.showStyle();

t2.showDim();

Console.WriteLine("Area is " + t2.area());

}

}

listing 4

// Demonstrate protected.

using System;

class B {

protected int i, j; // private to B, but accessible by D

public void set(int a, int b) {

i = a;

j = b;

}

public void show() {

Console.WriteLine(i + " " + j);

}

}

class D : B {

int k; // private

// D can access B's i and j

public void setk() {

k = i * j;

}

public void showk() {

Console.WriteLine(k);

}

}

class ProtectedDemo {

public static void Main() {

D ob = new D();

ob.set(2, 3); // OK, known to D

ob.show(); // OK, known to D

ob.setk(); // OK, part of D

ob.showk(); // OK, part of D

}

}

listing 5

// Add a constructor to Triangle.

using System;

// A class for two-dimensional objects.

class TwoDShape {

double pri_width; // private

double pri_height; // private

// properties for width and height.

public double width {

get { return pri_width; }

set { pri_width = value; }

}

public double height {

get { return pri_height; }

set { pri_height = value; }

}

public void showDim() {

Console.WriteLine("Width and height are " +

width + " and " + height);

}

}

// A derived class of TwoDShape for triangles.

class Triangle : TwoDShape {

string style; // private

// Constructor

public Triangle(string s, double w, double h) {

width = w; // init the base class

height = h; // init the base class

style = s; // init the derived class

}

// Return area of triangle.

public double area() {

return width * height / 2;

}

// Display a triangle's style.

public void showStyle() {

Console.WriteLine("Triangle is " + style);

}

}

class Shapes3 {

public static void Main() {

Triangle t1 = new Triangle("isosceles", 4.0, 4.0);

Triangle t2 = new Triangle("right", 8.0, 12.0);

Console.WriteLine("Info for t1: ");

t1.showStyle();

t1.showDim();

Console.WriteLine("Area is " + t1.area());

Console.WriteLine();

Console.WriteLine("Info for t2: ");

t2.showStyle();

t2.showDim();

Console.WriteLine("Area is " + t2.area());

}

}

listing 6

// Add constructors to TwoDShape.

using System;

// A class for two-dimensional objects.

class TwoDShape {

double pri_width; // private

double pri_height; // private

// Constructor for TwoDShape.

public TwoDShape(double w, double h) {

width = w;

height = h;

}

// properties for width and height.

public double width {

get { return pri_width; }

set { pri_width = value; }

}

public double height {

get { return pri_height; }

set { pri_height = value; }

}

public void showDim() {

Console.WriteLine("Width and height are " +

width + " and " + height);

}

}

// A derived class of TwoDShape for triangles.

class Triangle : TwoDShape {

string style; // private

// Call the base class constructor.

public Triangle(string s, double w, double h) : base(w, h) {

style = s;

}

// Return area of triangle.

public double area() {

return width * height / 2;

}

// Display a triangle's style.

public void showStyle() {

Console.WriteLine("Triangle is " + style);

}

}

class Shapes4 {

public static void Main() {

Triangle t1 = new Triangle("isosceles", 4.0, 4.0);

Triangle t2 = new Triangle("right", 8.0, 12.0);

Console.WriteLine("Info for t1: ");

t1.showStyle();

t1.showDim();

Console.WriteLine("Area is " + t1.area());

Console.WriteLine();

Console.WriteLine("Info for t2: ");

t2.showStyle();

t2.showDim();

Console.WriteLine("Area is " + t2.area());

}

}

listing 7

// Add more constructors to TwoDShape.

using System;

class TwoDShape {

double pri_width; // private

double pri_height; // private

// Default constructor.

public TwoDShape() {

width = height = 0.0;

}

// Constructor for TwoDShape.

public TwoDShape(double w, double h) {

width = w;

height = h;

}

// Construct object with equal width and height.

public TwoDShape(double x) {

width = height = x;

}

// Properties for width and height.

public double width {

get { return pri_width; }

set { pri_width = value; }

}

public double height {

get { return pri_height; }

set { pri_height = value; }

}

public void showDim() {

Console.WriteLine("Width and height are " +

width + " and " + height);

}

}

// A derived class of TwoDShape for triangles.

class Triangle : TwoDShape {

string style; // private

/* A default constructor. This automatically invokes

the default constructor of TwoDShape. */

public Triangle() {

style = "null";

}

// Constructor that takes three arguments.

public Triangle(string s, double w, double h) : base(w, h) {

style = s;

}

// Construct an isosceles triangle.

public Triangle(double x) : base(x) {

style = "isosceles";

}

// Return area of triangle.

public double area() {

return width * height / 2;

}

// Display a triangle's style.

public void showStyle() {

Console.WriteLine("Triangle is " + style);

}

}

class Shapes5 {

public static void Main() {

Triangle t1 = new Triangle();

Triangle t2 = new Triangle("right", 8.0, 12.0);

Triangle t3 = new Triangle(4.0);

t1 = t2;

Console.WriteLine("Info for t1: ");

t1.showStyle();

t1.showDim();

Console.WriteLine("Area is " + t1.area());

Console.WriteLine();

Console.WriteLine("Info for t2: ");

t2.showStyle();

t2.showDim();

Console.WriteLine("Area is " + t2.area());

Console.WriteLine();

Console.WriteLine("Info for t3: ");

t3.showStyle();

t3.showDim();

Console.WriteLine("Area is " + t3.area());

Console.WriteLine();

}

}

listing 8

// An example of inheritance-related name hiding.

using System;

class A {

public int i = 0;

}

// Create a derived class.

class B : A {

new int i; // this i hides the i in A

public B(int b) {

i = b; // i in B

}

public void show() {

Console.WriteLine("i in derived class: " + i);

}

}

class NameHiding {

public static void Main() {

B ob = new B(2);

ob.show();

}

}

listing 9

// Using base to overcome name hiding.

using System;

class A {

public int i = 0;

}

// Create a derived class.

class B : A {

new int i; // this i hides the i in A

public B(int a, int b) {

base.i = a; // this uncovers the i in A

i = b; // i in B

}

public void show() {

// this displays the i in A.

Console.WriteLine("i in base class: " + base.i);

// this displays the i in B

Console.WriteLine("i in derived class: " + i);

}

}

class UncoverName {

public static void Main() {

B ob = new B(1, 2);

ob.show();

}

}

listing 10

// Call a hidden method.

using System;

class A {

public int i = 0;

// show() in A

public void show() {

Console.WriteLine("i in base class: " + i);

}

}

// Create a derived class.

class B : A {

new int i; // this i hides the i in A

public B(int a, int b) {

base.i = a; // this uncovers the i in A

i = b; // i in B

}

// This hides show() in A. Notice the use of new.

new public void show() {

base.show(); // this calls show() in A

// this displays the i in B

Console.WriteLine("i in derived class: " + i);

}

}

class UncoverName {

public static void Main() {

B ob = new B(1, 2);

ob.show();

}

}

listing 11

// A multilevel hierarchy.

using System;

class TwoDShape {

double pri_width; // private

double pri_height; // private

// Default constructor.

public TwoDShape() {

width = height = 0.0;

}

// Constructor for TwoDShape.

public TwoDShape(double w, double h) {

width = w;

height = h;

}

// Construct object with equal width and height.

public TwoDShape(double x) {

width = height = x;

}

// Properties for width and height.

public double width {

get { return pri_width; }

set { pri_width = value; }

}

public double height {

get { return pri_height; }

set { pri_height = value; }

}

public void showDim() {

Console.WriteLine("Width and height are " +

width + " and " + height);

}

}

// A derived class of TwoDShape for triangles.

class Triangle : TwoDShape {

string style; // private

/* A default constructor. This invokes the default

constructor of TwoDShape. */

public Triangle() {

style = "null";

}

// Constructor

public Triangle(string s, double w, double h) : base(w, h) {

style = s;

}

// Construct an isosceles triangle.

public Triangle(double x) : base(x) {

style = "isosceles";

}

// Return area of triangle.

public double area() {

return width * height / 2;

}

// Display a triangle's style.

public void showStyle() {

Console.WriteLine("Triangle is " + style);

}

}

// Extend Triangle.

class ColorTriangle : Triangle {

string color;

public ColorTriangle(string c, string s,

double w, double h) : base(s, w, h) {

color = c;

}

// Display the color.

public void showColor() {

Console.WriteLine("Color is " + color);

}

}

class Shapes6 {

public static void Main() {

ColorTriangle t1 =

new ColorTriangle("Blue", "right", 8.0, 12.0);

ColorTriangle t2 =

new ColorTriangle("Red", "isosceles", 2.0, 2.0);

Console.WriteLine("Info for t1: ");

t1.showStyle();

t1.showDim();

t1.showColor();

Console.WriteLine("Area is " + t1.area());

Console.WriteLine();

Console.WriteLine("Info for t2: ");

t2.showStyle();

t2.showDim();

t2.showColor();

Console.WriteLine("Area is " + t2.area());

}

}

listing 12

// Demonstrate when constructors are called.

using System;

// Create a base class.

class A {

public A() {

Console.WriteLine("Constructing A.");

}

}

// Create a class derived from A.

class B : A {

public B() {

Console.WriteLine("Constructing B.");

}

}

// Create a class derived from B.

class C : B {

public C() {

Console.WriteLine("Constructing C.");

}

}

class OrderOfConstruction {

public static void Main() {

C c = new C();

}

}

listing 13

// This program will not compile.

class X {

int a;

public X(int i) { a = i; }

}

class Y {

int a;

public Y(int i) { a = i; }

}

class IncompatibleRef {

public static void Main() {

X x = new X(10);

X x2;

Y y = new Y(5);

x2 = x; // OK, both of same type

x2 = y; // Error, not of same type

}

}

listing 14

// A base class reference can refer to a derived class object.

using System;

class X {

public int a;

public X(int i) {

a = i;

}

}

class Y : X {

public int b;

public Y(int i, int j) : base(j) {

b = i;

}

}

class BaseRef {

public static void Main() {

X x = new X(10);

X x2;

Y y = new Y(5, 6);

x2 = x; // OK, both of same type

Console.WriteLine("x2.a: " + x2.a);

x2 = y; // Ok because Y is derived from X

Console.WriteLine("x2.a: " + x2.a);

// X references know only about X members

x2.a = 19; // OK

// x2.b = 27; // Error, X doesn't have a b member

}

}

listing 15

// Pass a derived class reference to a base class reference.

using System;

class TwoDShape {

double pri_width; // private

double pri_height; // private

// Default constructor.

public TwoDShape() {

width = height = 0.0;

}

// Constructor for TwoDShape.

public TwoDShape(double w, double h) {

width = w;

height = h;

}

// Construct object with equal width and height.

public TwoDShape(double x) {

width = height = x;

}

// Construct object from an object.

public TwoDShape(TwoDShape ob) {

width = ob.width;

height = ob.height;

}

// Properties for width and height.

public double width {

get { return pri_width; }

set { pri_width = value; }

}

public double height {

get { return pri_height; }

set { pri_height = value; }

}

public void showDim() {

Console.WriteLine("Width and height are " +

width + " and " + height);

}

}

// A derived class of TwoDShape for triangles.

class Triangle : TwoDShape {

string style; // private

// A default constructor.

public Triangle() {

style = "null";

}

// Constructor for Triangle.

public Triangle(string s, double w, double h) : base(w, h) {

style = s;

}

// Construct an isosceles triangle.

public Triangle(double x) : base(x) {

style = "isosceles";

}

// Construct an object from an object.

public Triangle(Triangle ob) : base(ob) {

style = ob.style;

}

// Return area of triangle.

public double area() {

return width * height / 2;

}

// Display a triangle's style.

public void showStyle() {

Console.WriteLine("Triangle is " + style);

}

}

class Shapes7 {

public static void Main() {

Triangle t1 = new Triangle("right", 8.0, 12.0);

// make a copy of t1

Triangle t2 = new Triangle(t1);

Console.WriteLine("Info for t1: ");

t1.showStyle();

t1.showDim();

Console.WriteLine("Area is " + t1.area());

Console.WriteLine();

Console.WriteLine("Info for t2: ");

t2.showStyle();

t2.showDim();

Console.WriteLine("Area is " + t2.area());

}

}

listing 16

// Demonstrate a virtual method.

using System;

class Base {

// Create virtual method in the base class.

public virtual void who() {

Console.WriteLine("who() in Base");

}

}

class Derived1 : Base {

// Override who() in a derived class.

public override void who() {

Console.WriteLine("who() in Derived1");

}

}

class Derived2 : Base {

// Override who() again in another derived class.

public override void who() {

Console.WriteLine("who() in Derived2");

}

}

class OverrideDemo {

public static void Main() {

Base baseOb = new Base();

Derived1 dOb1 = new Derived1();

Derived2 dOb2 = new Derived2();

Base baseRef; // a base-class reference

baseRef = baseOb;

baseRef.who();

baseRef = dOb1;

baseRef.who();

baseRef = dOb2;

baseRef.who();

}

}

listing 17

/* When a virtual method is not overridden,

the base class method is used. */

using System;

class Base {

// Create virtual method in the base class.

public virtual void who() {

Console.WriteLine("who() in Base");

}

}

class Derived1 : Base {

// Override who() in a derived class.

public override void who() {

Console.WriteLine("who() in Derived1");

}

}

class Derived2 : Base {

// This class does not override who().

}

class NoOverrideDemo {

public static void Main() {

Base baseOb = new Base();

Derived1 dOb1 = new Derived1();

Derived2 dOb2 = new Derived2();

Base baseRef; // a base-class reference

baseRef = baseOb;

baseRef.who();

baseRef = dOb1;

baseRef.who();

baseRef = dOb2;

baseRef.who(); // calls Base's who()

}

}

listing 18

/* In a multilevel hierarchy, the

first override of a virtual method

that is found while moving up the

hierarchy is the one executed. */

using System;

class Base {

// Create virtual method in the base class.

public virtual void who() {

Console.WriteLine("who() in Base");

}

}

class Derived1 : Base {

// Override who() in a derived class.

public override void who() {

Console.WriteLine("who() in Derived1");

}

}

class Derived2 : Derived1 {

// This class also does not override who().

}

class Derived3 : Derived2 {

// This class does not override who().

}

class NoOverrideDemo2 {

public static void Main() {

Derived3 dOb = new Derived3();

Base baseRef; // a base-class reference

baseRef = dOb;

baseRef.who(); // calls Derived1's who()

}

}

listing 19

// Use virtual methods and polymorphism.

using System;

class TwoDShape {

double pri_width; // private

double pri_height; // private

string pri_name; // private

// A default constructor.

public TwoDShape() {

width = height = 0.0;

name = "null";

}

// Parameterized constructor.

public TwoDShape(double w, double h, string n) {

width = w;

height = h;

name = n;

}

// Construct object with equal width and height.

public TwoDShape(double x, string n) {

width = height = x;

name = n;

}

// Construct an object from an object.

public TwoDShape(TwoDShape ob) {

width = ob.width;

height = ob.height;

name = ob.name;

}

// Properties for width, height, and name

public double width {

get { return pri_width; }

set { pri_width = value; }

}

public double height {

get { return pri_height; }

set { pri_height = value; }

}

public string name {

get { return pri_name; }

set { pri_name = value; }

}

public void showDim() {

Console.WriteLine("Width and height are " +

width + " and " + height);

}

public virtual double area() {

Console.WriteLine("area() must be overridden");

return 0.0;

}

}

// A derived class of TwoDShape for triangles.

class Triangle : TwoDShape {

string style; // private

// A default constructor.

public Triangle() {

style = "null";

}

// Constructor for Triangle.

public Triangle(string s, double w, double h) :

base(w, h, "triangle") {

style = s;

}

// Construct an isosceles triangle.

public Triangle(double x) : base(x, "triangle") {

style = "isosceles";

}

// Construct an object from an object.

public Triangle(Triangle ob) : base(ob) {

style = ob.style;

}

// Override area() for Triangle.

public override double area() {

return width * height / 2;

}

// Display a triangle's style.

public void showStyle() {

Console.WriteLine("Triangle is " + style);

}

}

// A derived class of TwoDShape for rectangles.

class Rectangle : TwoDShape {

// Constructor for Rectangle.

public Rectangle(double w, double h) :

base(w, h, "rectangle"){ }

// Construct a square.

public Rectangle(double x) :

base(x, "rectangle") { }

// Construct an object from an object.

public Rectangle(Rectangle ob) : base(ob) { }

// Return true if the rectangle is square.

public bool isSquare() {

if(width == height) return true;

return false;

}

// Override area() for Rectangle.

public override double area() {

return width * height;

}

}

class DynShapes {

public static void Main() {

TwoDShape[] shapes = new TwoDShape[5];

shapes[0] = new Triangle("right", 8.0, 12.0);

shapes[1] = new Rectangle(10);

shapes[2] = new Rectangle(10, 4);

shapes[3] = new Triangle(7.0);

shapes[4] = new TwoDShape(10, 20, "generic");

for(int i=0; i < shapes.Length; i++) {

Console.WriteLine("object is " + shapes[i].name);

Console.WriteLine("Area is " + shapes[i].area());

Console.WriteLine();

}

}

}

listing 20

// Create an abstract class.

using System;

abstract class TwoDShape {

double pri_width; // private

double pri_height; // private

string pri_name; // private

// A default constructor.

public TwoDShape() {

width = height = 0.0;

name = "null";

}

// Parameterized constructor.

public TwoDShape(double w, double h, string n) {

width = w;

height = h;

name = n;

}

// Construct object with equal width and height.

public TwoDShape(double x, string n) {

width = height = x;

name = n;

}

// Construct an object from an object.

public TwoDShape(TwoDShape ob) {

width = ob.width;

height = ob.height;

name = ob.name;

}

// Properties for width, height, and name

public double width {

get { return pri_width; }

set { pri_width = value; }

}

public double height {

get { return pri_height; }

set { pri_height = value; }

}

public string name {

get { return pri_name; }

set { pri_name = value; }

}

public void showDim() {

Console.WriteLine("Width and height are " +

width + " and " + height);

}

// Now, area() is abstract.

public abstract double area();

}

// A derived class of TwoDShape for triangles.

class Triangle : TwoDShape {

string style; // private

// A default constructor.

public Triangle() {

style = "null";

}

// Constructor for Triangle.

public Triangle(string s, double w, double h) :

base(w, h, "triangle") {

style = s;

}

// Construct an isosceles triangle.

public Triangle(double x) : base(x, "triangle") {

style = "isosceles";

}

// Construct an object from an object.

public Triangle(Triangle ob) : base(ob) {

style = ob.style;

}

// Override area() for Triangle.

public override double area() {

return width * height / 2;

}

// Display a triangle's style.

public void showStyle() {

Console.WriteLine("Triangle is " + style);

}

}

// A derived class of TwoDShape for rectangles.

class Rectangle : TwoDShape {

// Constructor for Rectangle.

public Rectangle(double w, double h) :

base(w, h, "rectangle"){ }

// Construct a square.

public Rectangle(double x) :

base(x, "rectangle") { }

// Construct an object from an object.

public Rectangle(Rectangle ob) : base(ob) { }

// Return true if the rectangle is square.

public bool isSquare() {

if(width == height) return true;

return false;

}

// Override area() for Rectangle.

public override double area() {

return width * height;

}

}

class AbsShape {

public static void Main() {

TwoDShape[] shapes = new TwoDShape[4];

shapes[0] = new Triangle("right", 8.0, 12.0);

shapes[1] = new Rectangle(10);

shapes[2] = new Rectangle(10, 4);

shapes[3] = new Triangle(7.0);

for(int i=0; i < shapes.Length; i++) {

Console.WriteLine("object is " + shapes[i].name);

Console.WriteLine("Area is " + shapes[i].area());

Console.WriteLine();

}

}

}

listing 21

// Demonstrate ToString()

using System;

class MyClass {

static int count = 0;

int id;

public MyClass() {

id = count;

count++;

}

public override string ToString() {

return "MyClass object #" + id;

}

}

class Test {

public static void Main() {

MyClass ob1 = new MyClass();

MyClass ob2 = new MyClass();

MyClass ob3 = new MyClass();

Console.WriteLine(ob1);

Console.WriteLine(ob2);

Console.WriteLine(ob3);

}

}

listing 22

// A simple boxing/unboxing example.

using System;

class BoxingDemo {

public static void Main() {

int x;

object obj;

x = 10;

obj = x; // box x into an object

int y = (int)obj; // unbox obj into an int

Console.WriteLine(y);

}

}

listing 23

// Boxing also occurs when passing values.

using System;

class BoxingDemo {

public static void Main() {

int x;

x = 10;

Console.WriteLine("Here is x: " + x);

// x is automatically boxed when passed to sqr()

x = BoxingDemo.sqr(x);

Console.WriteLine("Here is x squared: " + x);

}

static int sqr(object o) {

return (int)o * (int)o;

}

}

listing 24

// Boxing makes it possible to call methods on a value!

using System;

class MethOnValue {

public static void Main() {

Console.WriteLine(10.ToString());

}

}

listing 25

// Use object to create a generic array.

using System;

class GenericDemo {

public static void Main() {

object[] ga = new object[10];

// store ints

for(int i=0; i < 3; i++)

ga[i] = i;

// store doubles

for(int i=3; i < 6; i++)

ga[i] = (double) i / 2;

// store two strings, a bool, and a char

ga[6] = "Generic Array";

ga[7] = true;

ga[8] = 'X';

ga[9] = "end";

for(int i = 0; i < ga.Length; i++)

Console.WriteLine("ga[" + i + "]: " + ga[i] + " ");

}

}

listing 1

public interface ISeries {

int getNext(); // return next number in series

void reset(); // restart

void setStart(int x); // set starting value

}

listing 2

// Implement ISeries.

class ByTwos : ISeries {

int start;

int val;

public ByTwos() {

start = 0;

val = 0;

}

public int getNext() {

val += 2;

return val;

}

public void reset() {

val = start;

}

public void setStart(int x) {

start = x;

val = start;

}

}

listing 3

// Demonstrate the ByTwos interface.

using System;

class SeriesDemo {

public static void Main() {

ByTwos ob = new ByTwos();

for(int i=0; i < 5; i++)

Console.WriteLine("Next value is " +

ob.getNext());

Console.WriteLine("\nResetting");

ob.reset();

for(int i=0; i < 5; i++)

Console.WriteLine("Next value is " +

ob.getNext());

Console.WriteLine("\nStarting at 100");

ob.setStart(100);

for(int i=0; i < 5; i++)

Console.WriteLine("Next value is " +

ob.getNext());

}

}

listing 4

// Implement ISeries and add getPrevious().

class ByTwos : ISeries {

int start;

int val;

int prev;

public ByTwos() {

start = 0;

val = 0;

prev = -2;

}

public int getNext() {

prev = val;

val += 2;

return val;

}

public void reset() {

val = start;

prev = start - 2;

}

public void setStart(int x) {

start = x;

val = start;

prev = val - 2;

}

// A method not specified by ISeries.

public int getPrevious() {

return prev;

}

}

listing 5

// Use ISeries to implement a series of prime numbers.

class Primes : ISeries {

int start;

int val;

public Primes() {

start = 2;

val = 2;

}

public int getNext() {

int i, j;

bool isprime;

val++;

for(i = val; i < 1000000; i++) {

isprime = true;

for(j = 2; j < (i/j + 1); j++) {

if((i%j)==0) {

isprime = false;

break;

}

}

if(isprime) {

val = i;

break;

}

}

return val;

}

public void reset() {

val = start;

}

public void setStart(int x) {

start = x;

val = start;

}

}

listing 6

// Demonstrate interface references.

using System;

// Define the interface

public interface ISeries {

int getNext(); // return next number in series

void reset(); // restart

void setStart(int x); // set starting value

}

// Use ISeries to generate a sequence of even numbers.

class ByTwos : ISeries {

int start;

int val;

public ByTwos() {

start = 0;

val = 0;

}

public int getNext() {

val += 2;

return val;

}

public void reset() {

val = start;

}

public void setStart(int x) {

start = x;

val = start;

}

}

// Use ISeries to implement a series of prime numbers.

class Primes : ISeries {

int start;

int val;

public Primes() {

start = 2;

val = 2;

}

public int getNext() {

int i, j;

bool isprime;

val++;

for(i = val; i < 1000000; i++) {

isprime = true;

for(j = 2; j < (i/j + 1); j++) {

if((i%j)==0) {

isprime = false;

break;

}

}

if(isprime) {

val = i;

break;

}

}

return val;

}

public void reset() {

val = start;

}

public void setStart(int x) {

start = x;

val = start;

}

}

class SeriesDemo2 {

public static void Main() {

ByTwos twoOb = new ByTwos();

Primes primeOb = new Primes();

ISeries ob;

for(int i=0; i < 5; i++) {

ob = twoOb;

Console.WriteLine("Next ByTwos value is " +

ob.getNext());

ob = primeOb;

Console.WriteLine("Next prime number is " +

ob.getNext());

}

}

}

listing 7

// Use a property in an interface.

using System;

public interface ISeries {

// An interface property.

int next {

get; // return the next number in series

set; // set next number

}

}

// Implement ISeries.

class ByTwos : ISeries {

int val;

public ByTwos() {

val = 0;

}

// get or set value

public int next {

get {

val += 2;

return val;

}

set {

val = value;

}

}

}

// Demonstrate an interface property.

class SeriesDemo3 {

public static void Main() {

ByTwos ob = new ByTwos();

// access series through a property

for(int i=0; i < 5; i++)

Console.WriteLine("Next value is " + ob.next);

Console.WriteLine("\nStarting at 21");

ob.next = 21;

for(int i=0; i < 5; i++)

Console.WriteLine("Next value is " + ob.next);

}

}

listing 8

// Add an indexer in an interface.

using System;

public interface ISeries {

// an interface property

int next {

get; // return the next number in series

set; // set next number

}

// an interface indexer

int this[int index] {

get; // return the specified number in series

}

}

// Implement ISeries.

class ByTwos : ISeries {

int val;

public ByTwos() {

val = 0;

}

// get or set value using a property

public int next {

get {

val += 2;

return val;

}

set {

val = value;

}

}

// get a value using an index

public int this[int index] {

get {

val = 0;

for(int i=0; i<index; i++)

val += 2;

return val;

}

}

}

// Demonstrate an interface indexer.

class SeriesDemo4 {

public static void Main() {

ByTwos ob = new ByTwos();

// access series through a property

for(int i=0; i < 5; i++)

Console.WriteLine("Next value is " + ob.next);

Console.WriteLine("\nStarting at 21");

ob.next = 21;

for(int i=0; i < 5; i++)

Console.WriteLine("Next value is " +

ob.next);

Console.WriteLine("\nResetting to 0");

ob.next = 0;

// access series through an indexer

for(int i=0; i < 5; i++)

Console.WriteLine("Next value is " + ob[i]);

}

}

listing 9

// One interface can inherit another.

using System;

public interface A {

void meth1();

void meth2();

}

// B now includes meth1() and meth2() -- it adds meth3().

public interface B : A {

void meth3();

}

// This class must implement all of A and B

class MyClass : B {

public void meth1() {

Console.WriteLine("Implement meth1().");

}

public void meth2() {

Console.WriteLine("Implement meth2().");

}

public void meth3() {

Console.WriteLine("Implement meth3().");

}

}

class IFExtend {

public static void Main() {

MyClass ob = new MyClass();

ob.meth1();

ob.meth2();

ob.meth3();

}

}

listing 10

interface IMyIF {

int myMeth(int x);

}

listing 11

class MyClass : IMyIF {

int IMyIF.myMeth(int x) {

return x / 3;

}

}

listing 12

// Explicitly implement an interface member.

using System;

interface IEven {

bool isOdd(int x);

bool isEven(int x);

}

class MyClass : IEven {

// Explicit implementation. Notice that this member is private

// by default.

bool IEven.isOdd(int x) {

if((x%2) != 0) return true;

else return false;

}

// Normal implementation.

public bool isEven(int x) {

IEven o = this; // reference to invoking object

return !o.isOdd(x);

}

}

class Demo {

public static void Main() {

MyClass ob = new MyClass();

bool result;

result = ob.isEven(4);

if(result) Console.WriteLine("4 is even.");

// result = ob.isOdd(4); // Error, isOdd not directly accessible

// But, this is OK. It creates an IEven reference to a MyClass object

// and then calls isOdd() through that reference.

IEven iRef = (IEven) ob;

result = iRef.isOdd(3);

if(result) Console.WriteLine("3 is odd.");

}

}

listing 13

// Use explicit implementation to remove ambiguity.

using System;

interface IMyIF_A {

int meth(int x);

}

interface IMyIF_B {

int meth(int x);

}

// MyClass implements both interfaces.

class MyClass : IMyIF_A, IMyIF_B {

// explicitly implement the two meth()s

int IMyIF_A.meth(int x) {

return x + x;

}

int IMyIF_B.meth(int x) {

return x * x;

}

// call meth() through an interface reference.

public int methA(int x){

IMyIF_A a_ob;

a_ob = this;

return a_ob.meth(x); // calls IMyIF_A

}

public int methB(int x){

IMyIF_B b_ob;

b_ob = this;

return b_ob.meth(x); // calls IMyIF_B

}

}

class FQIFNames {

public static void Main() {

MyClass ob = new MyClass();

Console.Write("Calling IMyIF_A.meth(): ");

Console.WriteLine(ob.methA(3));

Console.Write("Calling IMyIF_B.meth(): ");

Console.WriteLine(ob.methB(3));

}

}

listing 14

// An encryption interface.

public interface ICipher {

string encode(string str);

string decode(string str);

}

listing 15

/* A simple implementation of ICipher that codes

a message by shifting each character 1 position

higher. Thus, A becomes B, and so on. */

class SimpleCipher : ICipher {

// Return an encoded string given plaintext.

public string encode(string str) {

string ciphertext = "";

for(int i=0; i < str.Length; i++)

ciphertext = ciphertext + (char) (str[i] + 1);

return ciphertext;

}

// Return a decoded string given ciphertext.

public string decode(string str) {

string plaintext = "";

for(int i=0; i < str.Length; i++)

plaintext = plaintext + (char) (str[i] - 1);

return plaintext;

}

}

/* This implementation of ICipher uses bit

manipulations and key. */

class BitCipher : ICipher {

ushort key;

// Specify a key when constructing BitCiphers.

public BitCipher(ushort k) {

key = k;

}

// Return an encoded string given plaintext.

public string encode(string str) {

string ciphertext = "";

for(int i=0; i < str.Length; i++)

ciphertext = ciphertext + (char) (str[i] ^ key);

return ciphertext;

}

// Return adecoded string given ciphertext.

public string decode(string str) {

string plaintext = "";

for(int i=0; i < str.Length; i++)

plaintext = plaintext + (char) (str[i] ^ key);

return plaintext;

}

}

listing 16

// Demonstrate ICipher.

using System;

class ICipherDemo {

public static void Main() {

ICipher ciphRef;

BitCipher bit = new BitCipher(27);

SimpleCipher sc = new SimpleCipher();

string plain;

string coded;

// first, ciphRef refers to the simple cipher

ciphRef = sc;

Console.WriteLine("Using simple cipher.");

plain = "testing";

coded = ciphRef.encode(plain);

Console.WriteLine("Cipher text: " + coded);

plain = ciphRef.decode(coded);

Console.WriteLine("Plain text: " + plain);

// now, let ciphRef refer to the bitwise cipher

ciphRef = bit;

Console.WriteLine("\nUsing bitwise cipher.");

plain = "testing";

coded = ciphRef.encode(plain);

Console.WriteLine("Cipher text: " + coded);

plain = ciphRef.decode(coded);

Console.WriteLine("Plain text: " + plain);

}

}

listing 17

// Use ICipher.

using System;

// A class for storing unlisted telephone numbers.

class UnlistedPhone {

string pri_name; // supports name property

string pri_number; // supports number property

ICipher crypt; // reference to encryption object

public UnlistedPhone(string name, string number, ICipher c)

{

crypt = c; // store encryption object

pri_name = crypt.encode(name);

pri_number = crypt.encode(number);

}

public string Name {

get {

return crypt.decode(pri_name);

}

set {

pri_name = crypt.encode(value);

}

}

public string Number {

get {

return crypt.decode(pri_number);

}

set {

pri_number = crypt.encode(value);

}

}

}

// Demonstrate UnlistedPhone

class UnlistedDemo {

public static void Main() {

UnlistedPhone phone1 =

new UnlistedPhone("Tom", "555-3456", new BitCipher(27));

UnlistedPhone phone2 =

new UnlistedPhone("Mary", "555-8891", new BitCipher(9));

Console.WriteLine("Unlisted number for " +

phone1.Name + " is " +

phone1.Number);

Console.WriteLine("Unlisted number for " +

phone2.Name + " is " +

phone2.Number);

}

}

listing 18

// This version uses SimpleCipher.

class UnlistedDemo {

public static void Main() {

// now, use SimpleCipher rather than BitCipher

UnlistedPhone phone1 =

new UnlistedPhone("Tom", "555-3456", new SimpleCipher());

UnlistedPhone phone2 =

new UnlistedPhone("Mary", "555-8891", new SimpleCipher());

Console.WriteLine("Unlisted number for " +

phone1.Name + " is " +

phone1.Number);

Console.WriteLine("Unlisted number for " +

phone2.Name + " is " +

phone2.Number);

}

}

listing 19

// Demonstrate a structure.

using System;

// Define a structure.

struct Book {

public string author;

public string title;

public int copyright;

public Book(string a, string t, int c) {

author = a;

title = t;

copyright = c;

}

}

// Demonstrate Book structure.

class StructDemo {

public static void Main() {

Book book1 = new Book("Herb Schildt",

"C#: The Complete Reference",

2005); // explicit constructor

Book book2 = new Book(); // default constructor

Book book3; // no constructor

Console.WriteLine(book1.title + " by " + book1.author +

", (c) " + book1.copyright);

Console.WriteLine();

if(book2.title == null)

Console.WriteLine("book2.title is null.");

// now, give book2 some info

book2.title = "Brave New World";

book2.author = "Aldous Huxley";

book2.copyright = 1932;

Console.Write("book2 now contains: ");

Console.WriteLine(book2.title + " by " + book2.author +

", (c) " + book2.copyright);

Console.WriteLine();

// Console.WriteLine(book3.title); // error, must initialize first

book3.title = "Red Storm Rising";

Console.WriteLine(book3.title); // now OK

}

}

listing 20

// Copy a struct.

using System;

// Define a structure.

struct MyStruct {

public int x;

}

// Demonstrate structure assignment.

class StructAssignment {

public static void Main() {

MyStruct a;

MyStruct b;

a.x = 10;

b.x = 20;

Console.WriteLine("a.x {0}, b.x {1}", a.x, b.x);

a = b;

b.x = 30;

Console.WriteLine("a.x {0}, b.x {1}", a.x, b.x);

}

}

listing 21

// Copy a class.

using System;

// Define a structure.

class MyClass {

public int x;

}

// Now show a class object assignment.

class ClassAssignment {

public static void Main() {

MyClass a = new MyClass();

MyClass b = new MyClass();

a.x = 10;

b.x = 20;

Console.WriteLine("a.x {0}, b.x {1}", a.x, b.x);

a = b;

b.x = 30;

Console.WriteLine("a.x {0}, b.x {1}", a.x, b.x);

}

}

listing 22

// Structures are good when grouping data.

using System;

// Define a packet structure.

struct PacketHeader {

public uint packNum; // packet number

public ushort packLen; // length of packet

}

// Use PacketHeader to create an e-commerce transaction record.

class Transaction {

static uint transacNum = 0;

PacketHeader ph; // incorporate PacketHeader into Transaction

string accountNum;

double amount;

public Transaction(string acc, double val) {

// create packet header

ph.packNum = transacNum++;

ph.packLen = 512; // arbitrary length

accountNum = acc;

amount = val;

}

// Simulate a transaction.

public void sendTransaction() {

Console.WriteLine("Packet #: " + ph.packNum +

", Length: " + ph.packLen +

",\n Account #: " + accountNum +

", Amount: {0:C}\n", amount);

}

}

// Demonstrate Packet

class PacketDemo {

public static void Main() {

Transaction t = new Transaction("31243", -100.12);

Transaction t2 = new Transaction("AB4655", 345.25);

Transaction t3 = new Transaction("8475-09", 9800.00);

t.sendTransaction();

t2.sendTransaction();

t3.sendTransaction();

}

}

listing 23

// Demonstrate an enumeration.

using System;

class EnumDemo {

enum Apple { Jonathan, GoldenDel, RedDel, Winesap,

Cortland, McIntosh };

public static void Main() {

string[] color = {

"Red",

"Yellow",

"Red",

"Red",

"Red",

"Reddish Green"

};

Apple i; // declare an enum variable

// use i to cycle through the enum

for(i = Apple.Jonathan; i <= Apple.McIntosh; i++)

Console.WriteLine(i + " has value of " + (int)i);

Console.WriteLine();

// use an enumeration to index an array

for(i = Apple.Jonathan; i <= Apple.McIntosh; i++)

Console.WriteLine("Color of " + i + " is " +

color[(int)i]);

}

}

listing 24

// Simulate a conveyor belt

using System;

class ConveyorControl {

// enumerate the conveyor commands

public enum Action { start, stop, forward, reverse };

public void conveyor(Action com) {

switch(com) {

case Action.start:

Console.WriteLine("Starting conveyor.");

break;

case Action.stop:

Console.WriteLine("Stopping conveyor.");

break;

case Action.forward:

Console.WriteLine("Moving forward.");

break;

case Action.reverse:

Console.WriteLine("Moving backward.");

break;

}

}

}

class ConveyorDemo {

public static void Main() {

ConveyorControl c = new ConveyorControl();

c.conveyor(ConveyorControl.Action.start);

c.conveyor(ConveyorControl.Action.forward);

c.conveyor(ConveyorControl.Action.reverse);

c.conveyor(ConveyorControl.Action.stop);

}

}

listing 1

// Demonstrate exception handling.

using System;

class ExcDemo1 {

public static void Main() {

int[] nums = new int[4];

try {

Console.WriteLine("Before exception is generated.");

// Generate an index out-of-bounds exception.

for(int i=0; i < 10; i++) {

nums[i] = i;

Console.WriteLine("nums[{0}]: {1}", i, nums[i]);

}

Console.WriteLine("this won't be displayed");

}

catch (IndexOutOfRangeException) {

// catch the exception

Console.WriteLine("Index out-of-bounds!");

}

Console.WriteLine("After catch statement.");

}

}

listing 2

/* An exception can be generated by one

method and caught by another. */

using System;

class ExcTest {

// Generate an exception.

public static void genException() {

int[] nums = new int[4];

Console.WriteLine("Before exception is generated.");

// Generate an index out-of-bounds exception.

for(int i=0; i < 10; i++) {

nums[i] = i;

Console.WriteLine("nums[{0}]: {1}", i, nums[i]);

}

Console.WriteLine("this won't be displayed");

}

}

class ExcDemo2 {

public static void Main() {

try {

ExcTest.genException();

}

catch (IndexOutOfRangeException) {

// catch the exception

Console.WriteLine("Index out-of-bounds!");

}

Console.WriteLine("After catch statement.");

}

}

listing 3

// Let the C# runtime system handle the error.

using System;

class NotHandled {

public static void Main() {

int[] nums = new int[4];

Console.WriteLine("Before exception is generated.");

// Generate an index out-of-bounds exception.

for(int i=0; i < 10; i++) {

nums[i] = i;

Console.WriteLine("nums[{0}]: {1}", i, nums[i]);

}

}

}

listing 4

// This won't work!

using System;

class ExcTypeMismatch {

public static void Main() {

int[] nums = new int[4];

try {

Console.WriteLine("Before exception is generated.");

// Generate an index out-of-bounds exception.

for(int i=0; i < 10; i++) {

nums[i] = i;

Console.WriteLine("nums[{0}]: {1}", i, nums[i]);

}

Console.WriteLine("this won't be displayed");

}

/* Can't catch an array boundary error with a

DivideByZeroException. */

catch (DivideByZeroException) {

// catch the exception

Console.WriteLine("Index out-of-bounds!");

}

Console.WriteLine("After catch statement.");

}

}

listing 5

// Handle error gracefully and continue.

using System;

class ExcDemo3 {

public static void Main() {

int[] numer = { 4, 8, 16, 32, 64, 128 };

int[] denom = { 2, 0, 4, 4, 0, 8 };

for(int i=0; i < numer.Length; i++) {

try {

Console.WriteLine(numer[i] + " / " +

denom[i] + " is " +

numer[i]/denom[i]);

}

catch (DivideByZeroException) {

// catch the exception

Console.WriteLine("Can't divide by Zero!");

}

}

}

}

listing 6

// Use multiple catch statements.

using System;

class ExcDemo4 {

public static void Main() {

// Here, numer is longer than denom.

int[] numer = { 4, 8, 16, 32, 64, 128, 256, 512 };

int[] denom = { 2, 0, 4, 4, 0, 8 };

for(int i=0; i < numer.Length; i++) {

try {

Console.WriteLine(numer[i] + " / " +

denom[i] + " is " +

numer[i]/denom[i]);

}

catch (DivideByZeroException) {

// catch the exception

Console.WriteLine("Can't divide by Zero!");

}

catch (IndexOutOfRangeException) {

// catch the exception

Console.WriteLine("No matching element found.");

}

}

}

}

listing 7

// Use the "catch all" catch statement.

using System;

class ExcDemo5 {

public static void Main() {

// Here, numer is longer than denom.

int[] numer = { 4, 8, 16, 32, 64, 128, 256, 512 };

int[] denom = { 2, 0, 4, 4, 0, 8 };

for(int i=0; i < numer.Length; i++) {

try {

Console.WriteLine(numer[i] + " / " +

denom[i] + " is " +

numer[i]/denom[i]);

}

catch {

Console.WriteLine("Some exception occurred.");

}

}

}

}

listing 8

// Use a nested try block.

using System;

class NestTrys {

public static void Main() {

// Here, numer is longer than denom.

int[] numer = { 4, 8, 16, 32, 64, 128, 256, 512 };

int[] denom = { 2, 0, 4, 4, 0, 8 };

try { // outer try

for(int i=0; i < numer.Length; i++) {

try { // nested try

Console.WriteLine(numer[i] + " / " +

denom[i] + " is " +

numer[i]/denom[i]);

}

catch (DivideByZeroException) {

// catch the exception

Console.WriteLine("Can't divide by Zero!");

}

}

}

catch (IndexOutOfRangeException) {

// catch the exception

Console.WriteLine("No matching element found.");

Console.WriteLine("Fatal error -- program terminated.");

}

}

}

listing 9

// Manually throw an exception.

using System;

class ThrowDemo {

public static void Main() {

try {

Console.WriteLine("Before throw.");

throw new DivideByZeroException();

}

catch (DivideByZeroException) {

// catch the exception

Console.WriteLine("Exception caught.");

}

Console.WriteLine("After try/catch block.");

}

}

listing 10

// Rethrow an exception.

using System;

class Rethrow {

public static void genException() {

// here, numer is longer than denom

int[] numer = { 4, 8, 16, 32, 64, 128, 256, 512 };

int[] denom = { 2, 0, 4, 4, 0, 8 };

for(int i=0; i<numer.Length; i++) {

try {

Console.WriteLine(numer[i] + " / " +

denom[i] + " is " +

numer[i]/denom[i]);

}

catch (DivideByZeroException) {

// catch the exception

Console.WriteLine("Can't divide by Zero!");

}

catch (IndexOutOfRangeException) {

// catch the exception

Console.WriteLine("No matching element found.");

throw; // rethrow the exception

}

}

}

}

class RethrowDemo {

public static void Main() {

try {

Rethrow.genException();

}

catch(IndexOutOfRangeException) {

// recatch exception

Console.WriteLine("Fatal error -- " +

"program terminated.");

}

}

}

listing 11

// Use finally.

using System;

class UseFinally {

public static void genException(int what) {

int t;

int[] nums = new int[2];

Console.WriteLine("Receiving " + what);

try {

switch(what) {

case 0:

t = 10 / what; // generate div-by-zero error

break;

case 1:

nums[4] = 4; // generate array index error.

break;

case 2:

return; // return from try block

}

}

catch (DivideByZeroException) {

// catch the exception

Console.WriteLine("Can't divide by Zero!");

return; // return from catch

}

catch (IndexOutOfRangeException) {

// catch the exception

Console.WriteLine("No matching element found.");

}

finally {

Console.WriteLine("Leaving try.");

}

}

}

class FinallyDemo {

public static void Main() {

for(int i=0; i < 3; i++) {

UseFinally.genException(i);

Console.WriteLine();

}

}

}

listing 12

// Using Exception members.

using System;

class ExcTest {

public static void genException() {

int[] nums = new int[4];

Console.WriteLine("Before exception is generated.");

// Generate an index out-of-bounds exception.

for(int i=0; i < 10; i++) {

nums[i] = i;

Console.WriteLine("nums[{0}]: {1}", i, nums[i]);

}

Console.WriteLine("this won't be displayed");

}

}

class UseExcept {

public static void Main() {

try {

ExcTest.genException();

}

catch (IndexOutOfRangeException exc) {

// catch the exception

Console.WriteLine("Standard message is: ");

Console.WriteLine(exc); // calls ToString()

Console.WriteLine("Stack trace: " + exc.StackTrace);

Console.WriteLine("Message: " + exc.Message);

Console.WriteLine("TargetSite: " + exc.TargetSite);

}

Console.WriteLine("After catch statement.");

}

}

listing 13

// Use the NullReferenceException.

using System;

class X {

int x;

public X(int a) {

x = a;

}

public int add(X o) {

return x + o.x;

}

}

// Demonstrate NullReferenceException.

class NREDemo {

public static void Main() {

X p = new X(10);

X q = null; // q is explicitly assigned null

int val;

try {

val = p.add(q); // this will lead to an exception

} catch (NullReferenceException) {

Console.WriteLine("NullReferenceException!");

Console.WriteLine("fixing...\n");

// now, fix it

q = new X(9);

val = p.add(q);

}

Console.WriteLine("val is {0}", val);

}

}

listing 14

// Use a custom Exception for RangeArray errors.

using System;

// Create a RangeArray exception.

class RangeArrayException : ApplicationException {

// Implement the standard constructors

public RangeArrayException() : base() { }

public RangeArrayException(string str) : base(str) { }

// Override ToString for RangeArrayException.

public override string ToString() {

return Message;

}

}

// An improved version of RangeArray.

class RangeArray {

// private data

int[] a; // reference to underlying array

int lowerBound; // lowest index

int upperBound; // greatest index

int len; // underlying var for Length property

// Construct array given its size.

public RangeArray(int low, int high) {

high++;

if(high <= low) {

throw new RangeArrayException("Low index not less than high.");

}

a = new int[high - low];

len = high - low;

lowerBound = low;

upperBound = --high;

}

// Read-only Length property.

public int Length {

get {

return len;

}

}

// This is the indexer for RangeArray.

public int this[int index] {

// This is the get accessor.

get {

if(ok(index)) {

return a[index - lowerBound];

} else {

throw new RangeArrayException("Range Error.");

}

}

// This is the set accessor.

set {

if(ok(index)) {

a[index - lowerBound] = value;

}

else throw new RangeArrayException("Range Error.");

}

}

// Return true if index is within bounds.

private bool ok(int index) {

if(index >= lowerBound & index <= upperBound) return true;

return false;

}

}

// Demonstrate the index-range array.

class RangeArrayDemo {

public static void Main() {

try {

RangeArray ra = new RangeArray(-5, 5);

RangeArray ra2 = new RangeArray(1, 10);

// Demonstrate ra

Console.WriteLine("Length of ra: " + ra.Length);

for(int i = -5; i <= 5; i++)

ra[i] = i;

Console.Write("Contents of ra: ");

for(int i = -5; i <= 5; i++)

Console.Write(ra[i] + " ");

Console.WriteLine("\n");

// Demonstrate ra2

Console.WriteLine("Length of ra2: " + ra2.Length);

for(int i = 1; i <= 10; i++)

ra2[i] = i;

Console.Write("Contents of ra2: ");

for(int i = 1; i <= 10; i++)

Console.Write(ra2[i] + " ");

Console.WriteLine("\n");

} catch (RangeArrayException exc) {

Console.WriteLine(exc);

}

// Now, demonstrate some errors.

Console.WriteLine("Now generate some range errors.");

// Use an invalid constructor.

try {

RangeArray ra3 = new RangeArray(100, -10); // Error

} catch (RangeArrayException exc) {

Console.WriteLine(exc);

}

// Use an invalid index.

try {

RangeArray ra3 = new RangeArray(-2, 2);

for(int i = -2; i <= 2; i++)

ra3[i] = i;

Console.Write("Contents of ra3: ");

for(int i = -2; i <= 10; i++) // generate range error

Console.Write(ra3[i] + " ");

} catch (RangeArrayException exc) {

Console.WriteLine(exc);

}

}

}

listing 15

// Derived exceptions must appear before base class exceptions.

using System;

// Create an exception.

class ExceptA : ApplicationException {

public ExceptA() : base() { }

public ExceptA(string str) : base(str) { }

public override string ToString() {

return Message;

}

}

// Create an exception derived from ExceptA

class ExceptB : ExceptA {

public ExceptB() : base() { }

public ExceptB(string str) : base(str) { }

public override string ToString() {

return Message;

}

}

class OrderMatters {

public static void Main() {

for(int x = 0; x < 3; x++) {

try {

if(x==0) throw new ExceptA("Caught an ExceptA exception");

else if(x==1) throw new ExceptB("Caught an ExceptB exception");

else throw new Exception();

}

catch (ExceptB exc) {

// catch the exception

Console.WriteLine(exc);

}

catch (ExceptA exc) {

// catch the exception

Console.WriteLine(exc);

}

catch (Exception exc) {

Console.WriteLine(exc);

}

}

}

}

listing 16

// Using checked and unchecked.

using System;

class CheckedDemo {

public static void Main() {

byte a, b;

byte result;

a = 127;

b = 127;

try {

result = unchecked((byte)(a * b));

Console.WriteLine("Unchecked result: " + result);

result = checked((byte)(a * b)); // this causes exception

Console.WriteLine("Checked result: " + result); // won't execute

}

catch (OverflowException exc) {

// catch the exception

Console.WriteLine(exc);

}

}

}

listing 17

// Using checked and unchecked with statement blocks.

using System;

class CheckedBlocks {

public static void Main() {

byte a, b;

byte result;

a = 127;

b = 127;

try {

unchecked {

a = 127;

b = 127;

result = unchecked((byte)(a * b));

Console.WriteLine("Unchecked result: " + result);

a = 125;

b = 5;

result = unchecked((byte)(a * b));

Console.WriteLine("Unchecked result: " + result);

}

checked {

a = 2;

b = 7;

result = checked((byte)(a * b)); // this is OK

Console.WriteLine("Checked result: " + result);

a = 127;

b = 127;

result = checked((byte)(a * b)); // this causes exception

Console.WriteLine("Checked result: " + result); // won't execute

}

}

catch (OverflowException exc) {

// catch the exception

Console.WriteLine(exc);

}

}

}

listing 1

// Read a character from the keyboard.

using System;

class KbIn {

public static void Main() {

char ch;

Console.Write("Press a key followed by ENTER: ");

ch = (char) Console.Read(); // get a char

Console.WriteLine("Your key is: " + ch);

}

}

listing 2

// Input from the console using ReadLine().

using System;

class ReadString {

public static void Main() {

string str;

Console.WriteLine("Enter some characters.");

str = Console.ReadLine();

Console.WriteLine("You entered: " + str);

}

}

listing 3

// Read a string from the keyboard, using Console.In directly.

using System;

class ReadChars2 {

public static void Main() {

string str;

Console.WriteLine("Enter some characters.");

str = Console.In.ReadLine(); // call TextReader's ReadLine() method

Console.WriteLine("You entered: " + str);

}

}

listing 4

// Read keystrokes from the console by

// using ReadKey().

using System;

class ReadKeys {

public static void Main() {

ConsoleKeyInfo keypress;

Console.WriteLine("Enter keystrokes. Enter Q to stop.");

do {

keypress = Console.ReadKey(); // read keystrokes

Console.WriteLine(" Your key is: " + keypress.KeyChar);

// Check for modifier keys.

if((ConsoleModifiers.Alt & keypress.Modifiers) != 0)

Console.WriteLine("Alt key pressed.");

if((ConsoleModifiers.Control & keypress.Modifiers) != 0)

Console.WriteLine("Control key pressed.");

if((ConsoleModifiers.Shift & keypress.Modifiers) != 0)

Console.WriteLine("Shift key pressed.");

} while(keypress.KeyChar != 'Q');

}

}

listing 5

// Write to Console.Out and Console.Error.

using System;

class ErrOut {

public static void Main() {

int a=10, b=0;

int result;

Console.Out.WriteLine("This will generate an exception.");

try {

result = a / b; // generate an exception

} catch(DivideByZeroException exc) {

Console.Error.WriteLine(exc.Message);

}

}

}

listing 6

FileStream fin;

try {

fin = new FileStream("test.dat", FileMode.Open);

}

catch(FileNotFoundException exc) {

Console.WriteLine(exc.Message);

return;

}

catch {

Console.WriteLine("Cannot open file.");

return;

}

listing 7

/* Display a text file.

To use this program, specify the name

of the file that you want to see.

For example, to see a file called TEST.CS,

use the following command line.

ShowFile TEST.CS

*/

using System;

using System.IO;

class ShowFile {

public static void Main(string[] args) {

int i;

FileStream fin;

try {

fin = new FileStream(args[0], FileMode.Open);

} catch(FileNotFoundException exc) {

Console.WriteLine(exc.Message);

return;

} catch(IndexOutOfRangeException exc) {

Console.WriteLine(exc.Message + "\nUsage: ShowFile File");

return;

}

// read bytes until EOF is encountered

do {

try {

i = fin.ReadByte();

} catch(Exception exc) {

Console.WriteLine(exc.Message);

return;

}

if(i != -1) Console.Write((char) i);

} while(i != -1);

fin.Close();

}

}

listing 8

// Write to a file.

using System;

using System.IO;

class WriteToFile {

public static void Main(string[] args) {

FileStream fout;

// open output file

try {

fout = new FileStream("test.txt", FileMode.Create);

} catch(IOException exc) {

Console.WriteLine(exc.Message + "\nError Opening Output File");

return;

}

// Write the alphabet to the file.

try {

for(char c = 'A'; c <= 'Z'; c++)

fout.WriteByte((byte) c);

} catch(IOException exc) {

Console.WriteLine(exc.Message + "File Error");

}

fout.Close();

}

}

listing 9

/* Copy a file.

To use this program, specify the name

of the source file and the destination file.

For example, to copy a file called FIRST.DAT

to a file called SECOND.DAT, use the following

command line.

CopyFile FIRST.DAT SECOND.DAT

*/

using System;

using System.IO;

class CopyFile {

public static void Main(string[] args) {

int i;

FileStream fin;

FileStream fout;

try {

// open input file

try {

fin = new FileStream(args[0], FileMode.Open);

} catch(FileNotFoundException exc) {

Console.WriteLine(exc.Message + "\nInput File Not Found");

return;

}

// open output file

try {

fout = new FileStream(args[1], FileMode.Create);

} catch(IOException exc) {

Console.WriteLine(exc.Message + "\nError Opening Output File");

return;

}

} catch(IndexOutOfRangeException exc) {

Console.WriteLine(exc.Message + "\nUsage: CopyFile From To");

return;

}

// Copy File

try {

do {

i = fin.ReadByte();

if(i != -1) fout.WriteByte((byte)i);

} while(i != -1);

} catch(IOException exc) {

Console.WriteLine(exc.Message + "File Error");

}

fin.Close();

fout.Close();

}

}

listing 10

/* A simple key-to-disk utility that

demonstrates a StreamWriter. */

using System;

using System.IO;

class KtoD {

public static void Main() {

string str;

FileStream fout;

try {

fout = new FileStream("test.txt", FileMode.Create);

}

catch(IOException exc) {

Console.WriteLine(exc.Message + "Cannot open file.");

return ;

}

StreamWriter fstr_out = new StreamWriter(fout);

Console.WriteLine("Enter text ('stop' to quit).");

do {

Console.Write(": ");

str = Console.ReadLine();

if(str != "stop") {

str = str + "\r\n"; // add newline

try {

fstr_out.Write(str);

} catch(IOException exc) {

Console.WriteLine(exc.Message + "File Error");

return ;

}

}

} while(str != "stop");

fstr_out.Close();

}

}

listing 11

// Open a file using StreamWriter.

using System;

using System.IO;

class KtoD {

public static void Main() {

string str;

StreamWriter fstr_out;

// Open the file directly using StreamWriter.

try {

fstr_out = new StreamWriter("test.txt");

}

catch(IOException exc) {

Console.WriteLine(exc.Message + "Cannot open file.");

return ;

}

Console.WriteLine("Enter text ('stop' to quit).");

do {

Console.Write(": ");

str = Console.ReadLine();

if(str != "stop") {

str = str + "\r\n"; // add newline

try {

fstr_out.Write(str);

} catch(IOException exc) {

Console.WriteLine(exc.Message + "File Error");

return ;

}

}

} while(str != "stop");

fstr_out.Close();

}

}

listing 12

/* A simple disk-to-screen utility that

demonstrates a FileReader. */

using System;

using System.IO;

class DtoS {

public static void Main() {

FileStream fin;

string s;

try {

fin = new FileStream("test.txt", FileMode.Open);

}

catch(FileNotFoundException exc) {

Console.WriteLine(exc.Message + "Cannot open file.");

return ;

}

StreamReader fstr_in = new StreamReader(fin);

// Read the file line-by-line.

while((s = fstr_in.ReadLine()) != null) {

Console.WriteLine(s);

}

fstr_in.Close();

}

}

listing 13

using System;

class Test {

public static void Main() {

Console.WriteLine("This is a test.");

}

}

listing 14

// Redirect Console.Out.

using System;

using System.IO;

class Redirect {

public static void Main() {

StreamWriter log_out;

try {

log_out = new StreamWriter("logfile.txt");

}

catch(IOException exc) {

Console.WriteLine(exc.Message + "Cannot open file.");

return ;

}

// Direct standard output to the log file.

Console.SetOut(log_out);

Console.WriteLine("This is the start of the log file.");

for(int i=0; i<10; i++) Console.WriteLine(i);

Console.WriteLine("This is the end of the log file.");

log_out.Close();

}

}

listing 15

// Write and then read back binary data.

using System;

using System.IO;

class RWData {

public static void Main() {

BinaryWriter dataOut;

BinaryReader dataIn;

int i = 10;

double d = 1023.56;

bool b = true;

try {

dataOut = new

BinaryWriter(new FileStream("testdata", FileMode.Create));

}

catch(IOException exc) {

Console.WriteLine(exc.Message + "\nCannot open file.");

return;

}

try {

Console.WriteLine("Writing " + i);

dataOut.Write(i);

Console.WriteLine("Writing " + d);

dataOut.Write(d);

Console.WriteLine("Writing " + b);

dataOut.Write(b);

Console.WriteLine("Writing " + 12.2 * 7.4);

dataOut.Write(12.2 * 7.4);

}

catch(IOException exc) {

Console.WriteLine(exc.Message + "\nWrite error.");

}

dataOut.Close();

Console.WriteLine();

// Now, read them back.

try {

dataIn = new

BinaryReader(new FileStream("testdata", FileMode.Open));

}

catch(FileNotFoundException exc) {

Console.WriteLine(exc.Message + "\nCannot open file.");

return;

}

try {

i = dataIn.ReadInt32();

Console.WriteLine("Reading " + i);

d = dataIn.ReadDouble();

Console.WriteLine("Reading " + d);

b = dataIn.ReadBoolean();

Console.WriteLine("Reading " + b);

d = dataIn.ReadDouble();

Console.WriteLine("Reading " + d);

}

catch(IOException exc) {

Console.WriteLine(exc.Message + "Read error.");

}

dataIn.Close();

}

}

listing 16

/* Use BinaryReader and BinaryWriter to implement

a simple inventory program. */

using System;

using System.IO;

class Inventory {

public static void Main() {

BinaryWriter dataOut;

BinaryReader dataIn;

string item; // name of item

int onhand; // number on hand

double cost; // cost

try {

dataOut = new

BinaryWriter(new FileStream("inventory.dat",

FileMode.Create));

}

catch(IOException exc) {

Console.WriteLine(exc.Message + "\nCannot open file.");

return;

}

// Write some inventory data to the file.

try {

dataOut.Write("Hammers");

dataOut.Write(10);

dataOut.Write(3.95);

dataOut.Write("Screwdrivers");

dataOut.Write(18);

dataOut.Write(1.50);

dataOut.Write("Pliers");

dataOut.Write(5);

dataOut.Write(4.95);

dataOut.Write("Saws");

dataOut.Write(8);

dataOut.Write(8.95);

}

catch(IOException exc) {

Console.WriteLine(exc.Message + "\nWrite error.");

}

dataOut.Close();

Console.WriteLine();

// Now, open inventory file for reading.

try {

dataIn = new

BinaryReader(new FileStream("inventory.dat",

FileMode.Open));

}

catch(FileNotFoundException exc) {

Console.WriteLine(exc.Message + "\nCannot open file.");

return;

}

// Lookup item entered by user.

Console.Write("Enter item to lookup: ");

string what = Console.ReadLine();

Console.WriteLine();

try {

for(;;) {

// Read an inventory entry.

item = dataIn.ReadString();

onhand = dataIn.ReadInt32();

cost = dataIn.ReadDouble();

/* See if the item matches the one requested.

If so, display information */

if(item.CompareTo(what) == 0) {

Console.WriteLine(onhand + " " + item + " on hand. " +

"Cost: {0:C} each", cost);

Console.WriteLine("Total value of {0}: {1:C}." ,

item, cost * onhand);

break;

}

}

}

catch(EndOfStreamException) {

Console.WriteLine("Item not found.");

}

catch(IOException exc) {

Console.WriteLine(exc.Message + "Read error.");

}

dataIn.Close();

}

}

listing 17

// Demonstrate random access.

using System;

using System.IO;

class RandomAccessDemo {

public static void Main() {

FileStream f;

char ch;

try {

f = new FileStream("random.dat", FileMode.Create);

}

catch(IOException exc) {

Console.WriteLine(exc.Message);

return ;

}

// Write the alphabet.

for(int i=0; i < 26; i++) {

try {

f.WriteByte((byte)('A'+i));

}

catch(IOException exc) {

Console.WriteLine(exc.Message);

return ;

}

}

try {

// Now, read back specific values

f.Seek(0, SeekOrigin.Begin); // seek to first byte

ch = (char) f.ReadByte();

Console.WriteLine("First value is " + ch);

f.Seek(1, SeekOrigin.Begin); // seek to second byte

ch = (char) f.ReadByte();

Console.WriteLine("Second value is " + ch);

f.Seek(4, SeekOrigin.Begin); // seek to 5th byte

ch = (char) f.ReadByte();

Console.WriteLine("Fifth value is " + ch);

Console.WriteLine();

// Now, read every other value.

Console.WriteLine("Here is every other value: ");

for(int i=0; i < 26; i += 2) {

f.Seek(i, SeekOrigin.Begin); // seek to ith double

ch = (char) f.ReadByte();

Console.Write(ch + " ");

}

}

catch(IOException exc) {

Console.WriteLine(exc.Message);

}

Console.WriteLine();

f.Close();

}

}

listing 18

// Demonstrate MemoryStream.

using System;

using System.IO;

class MemStrDemo {

public static void Main() {

byte[] storage = new byte[255];

// Create a memory-based stream.

MemoryStream memstrm = new MemoryStream(storage);

// Wrap memstrm in a reader and a writer.

StreamWriter memwtr = new StreamWriter(memstrm);

StreamReader memrdr = new StreamReader(memstrm);

// Write to storage, through memwtr.

for(int i=0; i < 10; i++)

memwtr.WriteLine("byte [" + i + "]: " + i);

// put a period at the end

memwtr.WriteLine(".");

memwtr.Flush();

Console.WriteLine("Reading from storage directly: ");

// Display contents of storage directly.

foreach(char ch in storage) {

if (ch == '.') break;

Console.Write(ch);

}

Console.WriteLine("\nReading through memrdr: ");

// Read from memstrm using the stream reader.

memstrm.Seek(0, SeekOrigin.Begin); // reset file pointer

string str = memrdr.ReadLine();

while(str != null) {

Console.WriteLine(str);

str = memrdr.ReadLine();

if(str.CompareTo(".") == 0) break;

}

}

}

listing 19

// Demonstrate StringReader and StringWriter

using System;

using System.IO;

class StrRdrDemo {

public static void Main() {

// Create a StringWriter

StringWriter strwtr = new StringWriter();

// Write to StringWriter.

for(int i=0; i < 10; i++)

strwtr.WriteLine("This is i: " + i);

// Create a StringReader

StringReader strrdr = new StringReader(strwtr.ToString());

// Now, read from StringReader.

string str = strrdr.ReadLine();

while(str != null) {

str = strrdr.ReadLine();

Console.WriteLine(str);

}

}

}

listing 20

// This program averages a list of numbers entered by the user.

using System;

using System.IO;

class AvgNums {

public static void Main() {

string str;

int n;

double sum = 0.0;

double avg, t;

Console.Write("How many numbers will you enter: ");

str = Console.ReadLine();

try {

n = Int32.Parse(str);

}

catch(FormatException exc) {

Console.WriteLine(exc.Message);

n = 0;

}

catch(OverflowException exc) {

Console.WriteLine(exc.Message);

n = 0;

}

Console.WriteLine("Enter " + n + " values.");

for(int i=0; i < n ; i++) {

Console.Write(": ");

str = Console.ReadLine();

try {

t = Double.Parse(str);

} catch(FormatException exc) {

Console.WriteLine(exc.Message);

t = 0.0;

}

catch(OverflowException exc) {

Console.WriteLine(exc.Message);

t = 0;

}

sum += t;

}

avg = sum / n;

Console.WriteLine("Average is " + avg);

}

}

listing 1

// A simple delegate example.

using System;

// Declare a delegate.

delegate string StrMod(string str);

class DelegateTest {

// Replaces spaces with hyphens.

static string replaceSpaces(string a) {

Console.WriteLine("Replaces spaces with hyphens.");

return a.Replace(' ', '-');

}

// Remove spaces.

static string removeSpaces(string a) {

string temp = "";

int i;

Console.WriteLine("Removing spaces.");

for(i=0; i < a.Length; i++)

if(a[i] != ' ') temp += a[i];

return temp;

}

// Reverse a string.

static string reverse(string a) {

string temp = "";

int i, j;

Console.WriteLine("Reversing string.");

for(j=0, i=a.Length-1; i >= 0; i--, j++)

temp += a[i];

return temp;

}

public static void Main() {

// Construct a delegate.

StrMod strOp = new StrMod(replaceSpaces);

string str;

// Call methods through the delegate.

str = strOp("This is a test.");

Console.WriteLine("Resulting string: " + str);

Console.WriteLine();

strOp = new StrMod(removeSpaces);

str = strOp("This is a test.");

Console.WriteLine("Resulting string: " + str);

Console.WriteLine();

strOp = new StrMod(reverse);

str = strOp("This is a test.");

Console.WriteLine("Resulting string: " + str);

}

}

listing 2

public static void Main() {

// Construct a delegate using method group conversion.

StrMod strOp = replaceSpaces; // use method group conversion

string str;

// Call methods through the delegate.

str = strOp("This is a test.");

Console.WriteLine("Resulting string: " + str);

Console.WriteLine();

strOp = removeSpaces; // use method group conversion

str = strOp("This is a test.");

Console.WriteLine("Resulting string: " + str);

Console.WriteLine();

strOp = reverse; // use method group converison

str = strOp("This is a test.");

Console.WriteLine("Resulting string: " + str);

}

listing 3

// Delegates can refer to instance methods, too.

using System;

// Declare a delegate.

delegate string StrMod(string str);

class StringOps {

// Replaces spaces with hyphens.

public string replaceSpaces(string a) {

Console.WriteLine("Replaces spaces with hyphens.");

return a.Replace(' ', '-');

}

// Remove spaces.

public string removeSpaces(string a) {

string temp = "";

int i;

Console.WriteLine("Removing spaces.");

for(i=0; i < a.Length; i++)

if(a[i] != ' ') temp += a[i];

return temp;

}

// Reverse a string.

public string reverse(string a) {

string temp = "";

int i, j;

Console.WriteLine("Reversing string.");

for(j=0, i=a.Length-1; i >= 0; i--, j++)

temp += a[i];

return temp;

}

}

class DelegateTest {

public static void Main() {

StringOps so = new StringOps(); // create an instance of StringOps

// Initialize a delegate.

StrMod strOp = so.replaceSpaces;

string str;

// Call methods through delegates.

str = strOp("This is a test.");

Console.WriteLine("Resulting string: " + str);

Console.WriteLine();

strOp = so.removeSpaces;

str = strOp("This is a test.");

Console.WriteLine("Resulting string: " + str);

Console.WriteLine();

strOp = so.reverse;

str = strOp("This is a test.");

Console.WriteLine("Resulting string: " + str);

}

}

listing 4

// Demonstrate multicasting.

using System;

// Declare a delegate.

delegate void StrMod(ref string str);

class MultiCastDemo {

// Replaces spaces with hyphens.

static void replaceSpaces(ref string a) {

Console.WriteLine("Replaces spaces with hyphens.");

a = a.Replace(' ', '-');

}

// Remove spaces.

static void removeSpaces(ref string a) {

string temp = "";

int i;

Console.WriteLine("Removing spaces.");

for(i=0; i < a.Length; i++)

if(a[i] != ' ') temp += a[i];

a = temp;

}

// Reverse a string.

static void reverse(ref string a) {

string temp = "";

int i, j;

Console.WriteLine("Reversing string.");

for(j=0, i=a.Length-1; i >= 0; i--, j++)

temp += a[i];

a = temp;

}

public static void Main() {

// Construct delegates.

StrMod strOp;

StrMod replaceSp = replaceSpaces;

StrMod removeSp = removeSpaces;

StrMod reverseStr = reverse;

string str = "This is a test";

// Set up multicast.

strOp = replaceSp;

strOp += reverseStr;

// Call multicast.

strOp(ref str);

Console.WriteLine("Resulting string: " + str);

Console.WriteLine();

// Remove replace and add remove.

strOp -= replaceSp;

strOp += removeSp;

str = "This is a test."; // reset string

// Call multicast.

strOp(ref str);

Console.WriteLine("Resulting string: " + str);

Console.WriteLine();

}

}

listing 5

// Demonstrate an anonymous method.

using System;

// Declare a delegate.

delegate void CountIt();

class AnonMethDemo {

public static void Main() {

// Here, the code for counting is passed

// as an anonymous method.

CountIt count = delegate {

// This is the block of code passed to the delegate.

for(int i=0; i <= 5; i++)

Console.WriteLine(i);

}; // notice the semicolon

count();

}

}

listing 6

// Demonstrate an anonymous method that takes an argument.

using System;

// Notice that CountIt now has a parameter.

delegate void CountIt(int end);

class AnonMethDemo2 {

public static void Main() {

// Here, the ending value for the count

// is passed to the anonymous method.

CountIt count = delegate (int end) {

for(int i=0; i <= end; i++)

Console.WriteLine(i);

};

count(3);

Console.WriteLine();

count(5);

}

}

listing 7

// Demonstrate an anonymous method that returns a value.

using System;

// This delegate returns a value.

delegate int CountIt(int end);

class AnonMethDemo3 {

public static void Main() {

int result;

// Here, the ending value for the count

// is passed to the anonymous method.

// A summation of the count is returned.

CountIt count = delegate (int end) {

int sum = 0;

for(int i=0; i <= end; i++) {

Console.WriteLine(i);

sum += i;

}

return sum; // return a value from an anonymous method

};

result = count(3);

Console.WriteLine("Summation of 3 is " + result);

Console.WriteLine();

result = count(5);

Console.WriteLine("Summation of 5 is " + result);

}

}

listing 8

// Demonstrate a captured variable.

using System;

// This delegate returns int and takes an int argument.

delegate int CountIt(int end);

class VarCapture {

static CountIt counter() {

int sum = 0;

// Here, a summation of the count is stored

// in the captured variable sum.

CountIt ctObj = delegate (int end) {

for(int i=0; i <= end; i++) {

Console.WriteLine(i);

sum += i;

}

return sum;

};

return ctObj;

}

public static void Main() {

// Get a counter

CountIt count = counter();

int result;

result = count(3);

Console.WriteLine("Summation of 3 is " + result);

Console.WriteLine();

result = count(5);

Console.WriteLine("Summation of 5 is " + result);

}

}

listing 9

// Demonstrate covariance and contravariance.

using System;

class X {

public int val;

}

// Y is derived from X.

class Y : X { }

// This delegate returns X and takes a Y argument.

delegate X ChangeIt(Y obj);

class CoContraVariance {

// This method returns X and has an X parameter.

static X incrA(X obj) {

X temp = new X();

temp.val = obj.val + 1;

return temp;

}

// This method returns Y and has an Y parameter.

static Y incrB(Y obj) {

Y temp = new Y();

temp.val = obj.val + 1;

return temp;

}

public static void Main() {

Y Yob = new Y();

// In this case, the parameter to incrA

// is X and the parameter to ChangeIt is Y.

// Because of contravariance, the following

// line is OK.

ChangeIt change = incrA;

X Xob = change(Yob);

Console.WriteLine("Xob: " + Xob.val);

// In the next case, the return type of

// incrB is Y and the return type of

// ChangeIt is X. Because of covariance,

// the following line is OK.

change = incrB;

Yob = (Y) change(Yob);

Console.WriteLine("Yob: " + Yob.val);

}

}

listing 10

// A very simple event demonstration.

using System;

// Declare a delegate for an event.

delegate void MyEventHandler();

// Declare an event class.

class MyEvent {

public event MyEventHandler SomeEvent;

// This is called to fire the event.

public void OnSomeEvent() {

if(SomeEvent != null)

SomeEvent();

}

}

class EventDemo {

// An event handler.

static void handler() {

Console.WriteLine("Event occurred");

}

public static void Main() {

MyEvent evt = new MyEvent();

// Add handler() to the event list.

evt.SomeEvent += handler;

// Fire the event.

evt.OnSomeEvent();

}

}

listing 11

// An event multicast demonstration.

using System;

// Declare a delegate for an event.

delegate void MyEventHandler();

// Declare an event class.

class MyEvent {

public event MyEventHandler SomeEvent;

// This is called to fire the event.

public void OnSomeEvent() {

if(SomeEvent != null)

SomeEvent();

}

}

class X {

public void Xhandler() {

Console.WriteLine("Event received by X object");

}

}

class Y {

public void Yhandler() {

Console.WriteLine("Event received by Y object");

}

}

class EventDemo2 {

static void handler() {

Console.WriteLine("Event received by EventDemo");

}

public static void Main() {

MyEvent evt = new MyEvent();

X xOb = new X();

Y yOb = new Y();

// Add handlers to the event list.

evt.SomeEvent += handler;

evt.SomeEvent += xOb.Xhandler;

evt.SomeEvent += yOb.Yhandler;

// Fire the event.

evt.OnSomeEvent();

Console.WriteLine();

// Remove a handler.

evt.SomeEvent -= xOb.Xhandler;

evt.OnSomeEvent();

}

}

listing 12

/* Individual objects receive notifications when instance

event handlers are used. */

using System;

// Declare a delegate for an event.

delegate void MyEventHandler();

// Declare an event class.

class MyEvent {

public event MyEventHandler SomeEvent;

// This is called to fire the event.

public void OnSomeEvent() {

if(SomeEvent != null)

SomeEvent();

}

}

class X {

int id;

public X(int x) { id = x; }

// This is an instance method that will be used as an event handler.

public void Xhandler() {

Console.WriteLine("Event received by object " + id);

}

}

class EventDemo3 {

public static void Main() {

MyEvent evt = new MyEvent();

X o1 = new X(1);

X o2 = new X(2);

X o3 = new X(3);

evt.SomeEvent += o1.Xhandler;

evt.SomeEvent += o2.Xhandler;

evt.SomeEvent += o3.Xhandler;

// Fire the event.

evt.OnSomeEvent();

}

}

listing 13

/* A class receives the notification when

a static method is used as an event handler. */

using System;

// Declare a delegate for an event.

delegate void MyEventHandler();

// Declare an event class.

class MyEvent {

public event MyEventHandler SomeEvent;

// This is called to fire the event.

public void OnSomeEvent() {

if(SomeEvent != null)

SomeEvent();

}

}

class X {

/* This is a static method that will be used as

an event handler. */

public static void Xhandler() {

Console.WriteLine("Event received by class.");

}

}

class EventDemo4 {

public static void Main() {

MyEvent evt = new MyEvent();

evt.SomeEvent += X.Xhandler;

// Fire the event.

evt.OnSomeEvent();

}

}

listing 14

// Create a custom means of managing the event invocation list.

using System;

// Declare a delegate for an event.

delegate void MyEventHandler();

// Declare an event class that holds up to 3 events.

class MyEvent {

MyEventHandler[] evnt = new MyEventHandler[3];

public event MyEventHandler SomeEvent {

// Add an event to the list.

add {

int i;

for(i=0; i < 3; i++)

if(evnt[i] == null) {

evnt[i] = value;

break;

}

if (i == 3) Console.WriteLine("Event list full.");

}

// Remove an event from the list.

remove {

int i;

for(i=0; i < 3; i++)

if(evnt[i] == value) {

evnt[i] = null;

break;

}

if (i == 3) Console.WriteLine("Event handler not found.");

}

}

// This is called to fire the events.

public void OnSomeEvent() {

for(int i=0; i < 3; i++)

if(evnt[i] != null) evnt[i]();

}

}

// Create some classes that use MyEventHandler.

class W {

public void Whandler() {

Console.WriteLine("Event received by W object");

}

}

class X {

public void Xhandler() {

Console.WriteLine("Event received by X object");

}

}

class Y {

public void Yhandler() {

Console.WriteLine("Event received by Y object");

}

}

class Z {

public void Zhandler() {

Console.WriteLine("Event received by Z object");

}

}

class EventDemo5 {

public static void Main() {

MyEvent evt = new MyEvent();

W wOb = new W();

X xOb = new X();

Y yOb = new Y();

Z zOb = new Z();

// Add handlers to the event list.

Console.WriteLine("Adding events.");

evt.SomeEvent += wOb.Whandler;

evt.SomeEvent += xOb.Xhandler;

evt.SomeEvent += yOb.Yhandler;

// Can't store this one -- full.

evt.SomeEvent += zOb.Zhandler;

Console.WriteLine();

// Fire the events.

evt.OnSomeEvent();

Console.WriteLine();

// Remove a handler.

Console.WriteLine("Remove xOb.Xhandler.");

evt.SomeEvent -= xOb.Xhandler;

evt.OnSomeEvent();

Console.WriteLine();

// Try to remove it again.

Console.WriteLine("Try to remove xOb.Xhandler again.");

evt.SomeEvent -= xOb.Xhandler;

evt.OnSomeEvent();

Console.WriteLine();

// Now, add Zhandler.

Console.WriteLine("Add zOb.Zhandler.");

evt.SomeEvent += zOb.Zhandler;

evt.OnSomeEvent();

}

}

listing 15

// A .NET-compatible event.

using System;

// Derive a class from EventArgs.

class MyEventArgs : EventArgs {

public int eventnum;

}

// Declare a delegate for an event.

delegate void MyEventHandler(object source, MyEventArgs arg);

// Declare an event class.

class MyEvent {

static int count = 0;

public event MyEventHandler SomeEvent;

// This fires SomeEvent.

public void OnSomeEvent() {

MyEventArgs arg = new MyEventArgs();

if(SomeEvent != null) {

arg.eventnum = count++;

SomeEvent(this, arg);

}

}

}

class X {

public void handler(object source, MyEventArgs arg) {

Console.WriteLine("Event " + arg.eventnum +

" received by an X object.");

Console.WriteLine("Source is " + source);

Console.WriteLine();

}

}

class Y {

public void handler(object source, MyEventArgs arg) {

Console.WriteLine("Event " + arg.eventnum +

" received by a Y object.");

Console.WriteLine("Source is " + source);

Console.WriteLine();

}

}

class EventDemo6 {

public static void Main() {

X ob1 = new X();

Y ob2 = new Y();

MyEvent evt = new MyEvent();

// Add handler() to the event list.

evt.SomeEvent += ob1.handler;

evt.SomeEvent += ob2.handler;

// Fire the event.

evt.OnSomeEvent();

evt.OnSomeEvent();

}

}

listing 16

// Use the built-in EventHandler delegate.

using System;

// Declare an event class.

class MyEvent {

public event EventHandler SomeEvent; // uses EventHandler delegate

// This is called to fire SomeEvent.

public void OnSomeEvent() {

if(SomeEvent != null)

SomeEvent(this, EventArgs.Empty);

}

}

class EventDemo {

static void handler(object source, EventArgs arg) {

Console.WriteLine("Event occurred");

Console.WriteLine("Source is " + source);

}

public static void Main() {

MyEvent evt = new MyEvent();

// Add handler() to the event list.

evt.SomeEvent += handler;

// Fire the event.

evt.OnSomeEvent();

}

}

listing 17

// Use an anonymous method as an event handler.

using System;

// Declare a delegate for an event.

delegate void MyEventHandler();

// Declare an event class.

class MyEvent {

public event MyEventHandler SomeEvent;

// This is called to fire the event.

public void OnSomeEvent() {

if(SomeEvent != null)

SomeEvent();

}

}

class AnonMethHandler {

public static void Main() {

MyEvent evt = new MyEvent();

// Use an anonymous method as an event handler.

evt.SomeEvent += delegate {

// This is the event handler.

Console.WriteLine("Event received.");

};

// Fire the event twice.

evt.OnSomeEvent();

evt.OnSomeEvent();

}

}

listing 18

// A keypress event example.

using System;

// Derive a custom EventArgs class that holds the key.

class KeyEventArgs : EventArgs {

public char ch;

}

// Declare a delegate for an event.

delegate void KeyHandler(object source, KeyEventArgs arg);

// Declare a keypress event class.

class KeyEvent {

public event KeyHandler KeyPress;

// This is called when a key is pressed.

public void OnKeyPress(char key) {

KeyEventArgs k = new KeyEventArgs();

if(KeyPress != null) {

k.ch = key;

KeyPress(this, k);

}

}

}

// Demonstrate KeyEvent.

class KeyEventDemo {

public static void Main() {

KeyEvent kevt = new KeyEvent();

ConsoleKeyInfo key;

int count = 0;

// Use anonymous method to display the keypress.

kevt.KeyPress += delegate(object source, KeyEventArgs arg) {

Console.WriteLine(" Received keystroke: " + arg.ch);

};

// Use an anonymous method to count keypresses.

kevt.KeyPress += delegate (object source, KeyEventArgs arg) {

count++; // count is an outer variable

};

Console.WriteLine("Enter some characters. " +

"Enter a period to stop.");

do {

key = Console.ReadKey();

kevt.OnKeyPress(key.KeyChar);

} while(key.KeyChar != '.');

Console.WriteLine(count + " keys pressed.");

}

}



listing 1

// Declare a namespace for counters.

namespace Counter {

// A simple countdown counter.

class CountDown {

int val;

public CountDown(int n) {

val = n;

}

public void reset(int n) {

val = n;

}

public int count() {

if(val > 0) return val--;

else return 0;

}

}

}

listing 2

// Demonstrate a namespace.

using System;

// Declare a namespace for counters.

namespace Counter {

// A simple countdown counter.

class CountDown {

int val;

public CountDown(int n) { val = n; }

public void reset(int n) {

val = n;

}

public int count() {

if(val > 0) return val--;

else return 0;

}

}

}

class NSDemo {

public static void Main() {

// Notice how CountDown is qualified by Counter.

Counter.CountDown cd1 = new Counter.CountDown(10);

int i;

do {

i = cd1.count();

Console.Write(i + " ");

} while(i > 0);

Console.WriteLine();

// Agian, notice how CountDown is qualified by Counter.

Counter.CountDown cd2 = new Counter.CountDown(20);

do {

i = cd2.count();

Console.Write(i + " ");

} while(i > 0);

Console.WriteLine();

cd2.reset(4);

do {

i = cd2.count();

Console.Write(i + " ");

} while(i > 0);

Console.WriteLine();

}

}

listing 3

// Namespaces prevent name conflicts.

using System;

// Declare a namespace for counters.

namespace Counter {

// A simple countdown counter.

class CountDown {

int val;

public CountDown(int n) {

val = n;

}

public void reset(int n) {

val = n;

}

public int count() {

if(val > 0) return val--;

else return 0;

}

}

}

// Declare another namespace.

namespace Counter2 {

/* This CountDown is in the default namespace and

does not conflict with the one in Counter. */

class CountDown {

public void count() {

Console.WriteLine("This is count() in the " +

"Counter2 namespace.");

}

}

}

class NSDemo2 {

public static void Main() {

// This is CountDown in the Counter namespace.

Counter.CountDown cd1 = new Counter.CountDown(10);

// This is CountDown in the default namespace.

Counter2.CountDown cd2 = new Counter2.CountDown();

int i;

do {

i = cd1.count();

Console.Write(i + " ");

} while(i > 0);

Console.WriteLine();

cd2.count();

}

}

listing 4

// Demonstrate the using directive.

using System;

// Bring Counter into view.

using Counter;

// Declare a namespace for counters.

namespace Counter {

// A simple countdown counter.

class CountDown {

int val;

public CountDown(int n) {

val = n;

}

public void reset(int n) {

val = n;

}

public int count() {

if(val > 0) return val--;

else return 0;

}

}

}

class NSDemo3 {

public static void Main() {

// now, CountDown can be used directly.

CountDown cd1 = new CountDown(10);

int i;

do {

i = cd1.count();

Console.Write(i + " ");

} while(i > 0);

Console.WriteLine();

CountDown cd2 = new CountDown(20);

do {

i = cd2.count();

Console.Write(i + " ");

} while(i > 0);

Console.WriteLine();

cd2.reset(4);

do {

i = cd2.count();

Console.Write(i + " ");

} while(i > 0);

Console.WriteLine();

}

}

listing 5

// Demonstrate a using alias.

using System;

// Create an alias for Counter.CountDown.

using Count = Counter.CountDown;

// Declare a namespace for counters.

namespace Counter {

// A simple countdown counter.

class CountDown {

int val;

public CountDown(int n) {

val = n;

}

public void reset(int n) {

val = n;

}

public int count() {

if(val > 0) return val--;

else return 0;

}

}

}

class NSDemo4 {

public static void Main() {

// Here, Count is used as a name for Counter.CountDown.

Count cd1 = new Count(10);

int i;

do {

i = cd1.count();

Console.Write(i + " ");

} while(i > 0);

Console.WriteLine();

Count cd2 = new Count(20);

do {

i = cd2.count();

Console.Write(i + " ");

} while(i > 0);

Console.WriteLine();

cd2.reset(4);

do {

i = cd2.count();

Console.Write(i + " ");

} while(i > 0);

Console.WriteLine();

}

}

listing 6

// Namespaces are additive.

using System;

// Bring Counter into view.

using Counter;

// Here is one Counter namespace.

namespace Counter {

// A simple countdown counter.

class CountDown {

int val;

public CountDown(int n) {

val = n;

}

public void reset(int n) {

val = n;

}

public int count() {

if(val > 0) return val--;

else return 0;

}

}

}

// Here is another Counter namespace.

namespace Counter {

// A simple count-up counter.

class CountUp {

int val;

int target;

public int Target {

get{

return target;

}

}

public CountUp(int n) {

target = n;

val = 0;

}

public void reset(int n) {

target = n;

val = 0;

}

public int count() {

if(val < target) return val++;

else return target;

}

}

}

class NSDemo5 {

public static void Main() {

CountDown cd = new CountDown(10);

CountUp cu = new CountUp(8);

int i;

do {

i = cd.count();

Console.Write(i + " ");

} while(i > 0);

Console.WriteLine();

do {

i = cu.count();

Console.Write(i + " ");

} while(i < cu.Target);

}

}

listing 7

// Namespaces can be nested.

using System;

namespace NS1 {

class ClassA {

public ClassA() {

Console.WriteLine("constructing ClassA");

}

}

namespace NS2 { // a nested namespace

class ClassB {

public ClassB() {

Console.WriteLine("constructing ClassB");

}

}

}

}

class NestedNSDemo {

public static void Main() {

NS1.ClassA a = new NS1.ClassA();

// NS2.ClassB b = new NS2.ClassB(); // Error!!! NS2 is not in view

NS1.NS2.ClassB b = new NS1.NS2.ClassB(); // this is right

}

}

listing 8

// Demonstrate why the :: qualifier is needed.

//

// This program will not compile.

using System;

// Use both the Counter and AnotherCounter namespace

using Counter;

using AnotherCounter;

// Declare a namespace for counters.

namespace Counter {

// A simple countdown counter.

class CountDown {

int val;

public CountDown(int n) {

val = n;

}

// ...

}

}

// Declare another namespaces for counters.

namespace AnotherCounter {

// Declare another class called CountDown, which

// is in the global namespace.

class CountDown {

int val;

public CountDown(int n) {

val = n;

}

// ...

}

}

class WhyAliasQualifier {

public static void Main() {

int i;

// The following line is inherently ambiguous!

// Does it refer to CountDown in Counter or

// to CountDown in AnotherCounter?

CountDown cd1 = new CountDown(10); // Error! ! !

// ...

}

}

listing 9

// Demonstrate the :: qualifier.

using System;

using Counter;

using AnotherCounter;

// Give Counter an alias called Ctr.

using Ctr = Counter;

// Declare a namespace for counters.

namespace Counter {

// A simple countdown counter.

class CountDown {

int val;

public CountDown(int n) {

val = n;

}

// ...

}

}

// Another counter namespace.

namespace AnotherCounter {

// Declare another class called CountDown, which

// is in the global namespace.

class CountDown {

int val;

public CountDown(int n) {

val = n;

}

// ...

}

}

class AliasQualifierDemo {

public static void Main() {

// Here, the :: operator to resolves

// tells the compiler to use the CountDown

// that is in the Counter namespace.

Ctr::CountDown cd1 = new Ctr::CountDown(10);

// ...

}

}

listing 10

// Use the global alias.

using System;

// Give Counter an alias called Ctr.

using Ctr = Counter;

// Declare a namespace for counters.

namespace Counter {

// A simple countdown counter.

class CountDown {

int val;

public CountDown(int n) {

val = n;

}

// ...

}

}

// Declare another class called CountDown, which

// is in the global namespace.

class CountDown {

int val;

public CountDown(int n) {

val = n;

}

// ...

}

class GlobalAliasQualifierDemo {

public static void Main() {

// Here, the :: qualifier tells the compiler

// to use the CountDown to use the Counter namespace.

Ctr::CountDown cd1 = new Ctr::CountDown(10);

// Next, create CountDown object from global namespace.

global::CountDown cd2 = new global::CountDown(10);

// ...

}

}

listing 11

// Demonstrate #if, #endif, and #define.

#define EXPERIMENTAL

using System;

class Test {

public static void Main() {

#if EXPERIMENTAL

Console.WriteLine("Compiled for experimental version.");

#endif

Console.WriteLine("This is in all versions.");

}

}

listing 12

// Use a symbol expression.

#define EXPERIMENTAL

#define TRIAL

using System;

class Test {

public static void Main() {

#if EXPERIMENTAL

Console.WriteLine("Compiled for experimental version.");

#endif

#if EXPERIMENTAL && TRIAL

Console.Error.WriteLine("Testing experimental trial version.");

#endif

Console.WriteLine("This is in all versions.");

}

}

listing 13

// Demonstrate #else.

#define EXPERIMENTAL

using System;

class Test {

public static void Main() {

#if EXPERIMENTAL

Console.WriteLine("Compiled for experimental version.");

#else

Console.WriteLine("Compiled for release.");

#endif

#if EXPERIMENTAL && TRIAL

Console.Error.WriteLine("Testing experimental trial version.");

#else

Console.Error.WriteLine("Not experimental trial version.");

#endif

Console.WriteLine("This is in all versions.");

}

}

listing 14

// Demonstrate #elif.

#define RELEASE

using System;

class Test {

public static void Main() {

#if EXPERIMENTAL

Console.WriteLine("Compiled for experimental version.");

#elif RELEASE

Console.WriteLine("Compiled for release.");

#else

Console.WriteLine("Compiled for internal testing.");

#endif

#if TRIAL && !RELEASE

Console.WriteLine("Trial version.");

#endif

Console.WriteLine("This is in all versions.");

}

}

listing 15

// Use internal.

using System;

class InternalTest {

internal int x;

}

class InternalDemo {

public static void Main() {

InternalTest ob = new InternalTest();

ob.x = 10; // can access -- in same file

Console.WriteLine("Here is ob.x: " + ob.x);

}

}

listing 1

// Demonstrate is.

using System;

class A {}

class B : A {}

class UseIs {

public static void Main() {

A a = new A();

B b = new B();

if(a is A) Console.WriteLine("a is an A");

if(b is A)

Console.WriteLine("b is an A because it is derived from A");

if(a is B)

Console.WriteLine("This won't display -- a not derived from B");

if(b is B) Console.WriteLine("B is a B");

if(a is object) Console.WriteLine("a is an object");

}

}

listing 2

// Use is to avoid an invalid cast.

using System;

class A {}

class B : A {}

class CheckCast {

public static void Main() {

A a = new A();

B b = new B();

// Check to see if a can be cast to B.

if(a is B) // if so, do the cast

b = (B) a;

else // if not, skip the cast

b = null;

if(b==null)

Console.WriteLine("Cast b = (B) a is NOT allowed.");

else

Console.WriteLine("Cast b = (B) a is allowed");

}

}

listing 3

// Demonstrate as.

using System;

class A {}

class B : A {}

class CheckCast {

public static void Main() {

A a = new A();

B b = new B();

b = a as B; // cast, if possible

if(b==null)

Console.WriteLine("Cast b = (B) a is NOT allowed.");

else

Console.WriteLine("Cast b = (B) a is allowed");

}

}

listing 4

// Demonstrate typeof.

using System;

using System.IO;

class UseTypeof {

public static void Main() {

Type t = typeof(StreamReader);

Console.WriteLine(t.FullName);

if(t.IsClass) Console.WriteLine("Is a class.");

if(t.IsAbstract) Console.WriteLine("Is abstract.");

else Console.WriteLine("Is concrete.");

}

}

listing 5

// Analyze methods using reflection.

using System;

using System.Reflection;

class MyClass {

int x;

int y;

public MyClass(int i, int j) {

x = i;

y = j;

}

public int sum() {

return x+y;

}

public bool isBetween(int i) {

if(x < i && i < y) return true;

else return false;

}

public void set(int a, int b) {

x = a;

y = b;

}

public void set(double a, double b) {

x = (int) a;

y = (int) b;

}

public void show() {

Console.WriteLine(" x: {0}, y: {1}", x, y);

}

}

class ReflectDemo {

public static void Main() {

Type t = typeof(MyClass); // get a Type object representing MyClass

Console.WriteLine("Analyzing methods in " + t.Name);

Console.WriteLine();

Console.WriteLine("Methods supported: ");

MethodInfo[] mi = t.GetMethods();

// Display methods supported by MyClass.

foreach(MethodInfo m in mi) {

// Display return type and name.

Console.Write(" " + m.ReturnType.Name +

" " + m.Name + "(");

// Display parameters.

ParameterInfo[] pi = m.GetParameters();

for(int i=0; i < pi.Length; i++) {

Console.Write(pi[i].ParameterType.Name +

" " + pi[i].Name);

if(i+1 < pi.Length) Console.Write(", ");

}

Console.WriteLine(")");

Console.WriteLine();

}

}

}

listing 6

// Invoke methods using reflection.

using System;

using System.Reflection;

class MyClass {

int x;

int y;

public MyClass(int i, int j) {

x = i;

y = j;

}

public int sum() {

return x+y;

}

public bool isBetween(int i) {

if((x < i) && (i < y)) return true;

else return false;

}

public void set(int a, int b) {

Console.Write("Inside set(int, int). ");

x = a;

y = b;

show();

}

// Overload set.

public void set(double a, double b) {

Console.Write("Inside set(double, double). ");

x = (int) a;

y = (int) b;

show();

}

public void show() {

Console.WriteLine("Values are x: {0}, y: {1}", x, y);

}

}

class InvokeMethDemo {

public static void Main() {

Type t = typeof(MyClass);

MyClass reflectOb = new MyClass(10, 20);

int val;

Console.WriteLine("Invoking methods in " + t.Name);

Console.WriteLine();

MethodInfo[] mi = t.GetMethods();

// Invoke each method.

foreach(MethodInfo m in mi) {

// Get the parameters.

ParameterInfo[] pi = m.GetParameters();

if(m.Name.CompareTo("set")==0 &&

pi[0].ParameterType == typeof(int)) {

object[] args = new object[2];

args[0] = 9;

args[1] = 18;

m.Invoke(reflectOb, args);

}

else if(m.Name.CompareTo("set")==0 &&

pi[0].ParameterType == typeof(double)) {

object[] args = new object[2];

args[0] = 1.12;

args[1] = 23.4;

m.Invoke(reflectOb, args);

}

else if(m.Name.CompareTo("sum")==0) {

val = (int) m.Invoke(reflectOb, null);

Console.WriteLine("sum is " + val);

}

else if(m.Name.CompareTo("isBetween")==0) {

object[] args = new object[1];

args[0] = 14;

if((bool) m.Invoke(reflectOb, args))

Console.WriteLine("14 is between x and y");

}

else if(m.Name.CompareTo("show")==0) {

m.Invoke(reflectOb, null);

}

}

}

}

listing 7

// Create an object using reflection.

using System;

using System.Reflection;

class MyClass {

int x;

int y;

public MyClass(int i) {

Console.WriteLine("Constructing MyClass(int, int). ");

x = y = i;

}

public MyClass(int i, int j) {

Console.WriteLine("Constructing MyClass(int, int). ");

x = i;

y = j;

show();

}

public int sum() {

return x+y;

}

public bool isBetween(int i) {

if((x < i) && (i < y)) return true;

else return false;

}

public void set(int a, int b) {

Console.Write("Inside set(int, int). ");

x = a;

y = b;

show();

}

// Overload set.

public void set(double a, double b) {

Console.Write("Inside set(double, double). ");

x = (int) a;

y = (int) b;

show();

}

public void show() {

Console.WriteLine("Values are x: {0}, y: {1}", x, y);

}

}

class InvokeConsDemo {

public static void Main() {

Type t = typeof(MyClass);

int val;

// Get constructor info.

ConstructorInfo[] ci = t.GetConstructors();

Console.WriteLine("Available constructors: ");

foreach(ConstructorInfo c in ci) {

// Display return type and name.

Console.Write(" " + t.Name + "(");

// Display parameters.

ParameterInfo[] pi = c.GetParameters();

for(int i=0; i < pi.Length; i++) {

Console.Write(pi[i].ParameterType.Name +

" " + pi[i].Name);

if(i+1 < pi.Length) Console.Write(", ");

}

Console.WriteLine(")");

}

Console.WriteLine();

// Find matching constructor.

int x;

for(x=0; x < ci.Length; x++) {

ParameterInfo[] pi = ci[x].GetParameters();

if(pi.Length == 2) break;

}

if(x == ci.Length) {

Console.WriteLine("No matching constructor found.");

return;

}

else

Console.WriteLine("Two-parameter constructor found.\n");

// Construct the object.

object[] consargs = new object[2];

consargs[0] = 10;

consargs[1] = 20;

object reflectOb = ci[x].Invoke(consargs);

Console.WriteLine("\nInvoking methods on reflectOb.");

Console.WriteLine();

MethodInfo[] mi = t.GetMethods();

// Invoke each method.

foreach(MethodInfo m in mi) {

// Get the parameters.

ParameterInfo[] pi = m.GetParameters();

if(m.Name.CompareTo("set")==0 &&

pi[0].ParameterType == typeof(int)) {

// This is set(int, int).

object[] args = new object[2];

args[0] = 9;

args[1] = 18;

m.Invoke(reflectOb, args);

}

else if(m.Name.CompareTo("set")==0 &&

pi[0].ParameterType == typeof(double)) {

// This is set(double, double).

object[] args = new object[2];

args[0] = 1.12;

args[1] = 23.4;

m.Invoke(reflectOb, args);

}

else if(m.Name.CompareTo("sum")==0) {

val = (int) m.Invoke(reflectOb, null);

Console.WriteLine("sum is " + val);

}

else if(m.Name.CompareTo("isBetween")==0) {

object[] args = new object[1];

args[0] = 14;

if((bool) m.Invoke(reflectOb, args))

Console.WriteLine("14 is between x and y");

}

else if(m.Name.CompareTo("show")==0) {

m.Invoke(reflectOb, null);

}

}

}

}

listing 8

// A file that contains three classes. Call this file MyClasses.cs.

using System;

class MyClass {

int x;

int y;

public MyClass(int i) {

Console.WriteLine("Constructing MyClass(int). ");

x = y = i;

show();

}

public MyClass(int i, int j) {

Console.WriteLine("Constructing MyClass(int, int). ");

x = i;

y = j;

show();

}

public int sum() {

return x+y;

}

public bool isBetween(int i) {

if((x < i) && (i < y)) return true;

else return false;

}

public void set(int a, int b) {

Console.Write("Inside set(int, int). ");

x = a;

y = b;

show();

}

// Overload set.

public void set(double a, double b) {

Console.Write("Inside set(double, double). ");

x = (int) a;

y = (int) b;

show();

}

public void show() {

Console.WriteLine("Values are x: {0}, y: {1}", x, y);

}

}

class AnotherClass {

string remark;

public AnotherClass(string str) {

remark = str;

}

public void show() {

Console.WriteLine(remark);

}

}

class Demo {

public static void Main() {

Console.WriteLine("This is a placeholder.");

}

}

listing 9

/* Locate an assembly, determine types, and create

an object using reflection. */

using System;

using System.Reflection;

class ReflectAssemblyDemo {

public static void Main() {

int val;

// Load the MyClasses.exe assembly.

Assembly asm = Assembly.LoadFrom("MyClasses.exe");

// Discover what types MyClasses.exe contains.

Type[] alltypes = asm.GetTypes();

foreach(Type temp in alltypes)

Console.WriteLine("Found: " + temp.Name);

Console.WriteLine();

// Use the first type, which is MyClass in this case.

Type t = alltypes[0]; // use first class found

Console.WriteLine("Using: " + t.Name);

// Obtain constructor info.

ConstructorInfo[] ci = t.GetConstructors();

Console.WriteLine("Available constructors: ");

foreach(ConstructorInfo c in ci) {

// Display return type and name.

Console.Write(" " + t.Name + "(");

// Display parameters.

ParameterInfo[] pi = c.GetParameters();

for(int i=0; i < pi.Length; i++) {

Console.Write(pi[i].ParameterType.Name +

" " + pi[i].Name);

if(i+1 < pi.Length) Console.Write(", ");

}

Console.WriteLine(")");

}

Console.WriteLine();

// Find matching constructor.

int x;

for(x=0; x < ci.Length; x++) {

ParameterInfo[] pi = ci[x].GetParameters();

if(pi.Length == 2) break;

}

if(x == ci.Length) {

Console.WriteLine("No matching constructor found.");

return;

}

else

Console.WriteLine("Two-parameter constructor found.\n");

// Construct the object.

object[] consargs = new object[2];

consargs[0] = 10;

consargs[1] = 20;

object reflectOb = ci[x].Invoke(consargs);

Console.WriteLine("\nInvoking methods on reflectOb.");

Console.WriteLine();

MethodInfo[] mi = t.GetMethods();

// Invoke each method.

foreach(MethodInfo m in mi) {

// Get the parameters.

ParameterInfo[] pi = m.GetParameters();

if(m.Name.CompareTo("set")==0 &&

pi[0].ParameterType == typeof(int)) {

// This is set(int, int).

object[] args = new object[2];

args[0] = 9;

args[1] = 18;

m.Invoke(reflectOb, args);

}

else if(m.Name.CompareTo("set")==0 &&

pi[0].ParameterType == typeof(double)) {

// This is set(double, double).

object[] args = new object[2];

args[0] = 1.12;

args[1] = 23.4;

m.Invoke(reflectOb, args);

}

else if(m.Name.CompareTo("sum")==0) {

val = (int) m.Invoke(reflectOb, null);

Console.WriteLine("sum is " + val);

}

else if(m.Name.CompareTo("isBetween")==0) {

object[] args = new object[1];

args[0] = 14;

if((bool) m.Invoke(reflectOb, args))

Console.WriteLine("14 is between x and y");

}

else if(m.Name.CompareTo("show")==0) {

m.Invoke(reflectOb, null);

}

}

}

}

listing 10

// Utilize MyClass without assuming any prior knowledge.

using System;

using System.Reflection;

class ReflectAssemblyDemo {

public static void Main() {

int val;

Assembly asm = Assembly.LoadFrom("MyClasses.exe");

Type[] alltypes = asm.GetTypes();

Type t = alltypes[0]; // use first class found

Console.WriteLine("Using: " + t.Name);

ConstructorInfo[] ci = t.GetConstructors();

// Use first constructor found.

ParameterInfo[] cpi = ci[0].GetParameters();

object reflectOb;

if(cpi.Length > 0) {

object[] consargs = new object[cpi.Length];

// initialize args

for(int n=0; n < cpi.Length; n++)

consargs
= 10 + n * 20;

// construct the object

reflectOb = ci[0].Invoke(consargs);

} else

reflectOb = ci[0].Invoke(null);

Console.WriteLine("\nInvoking methods on reflectOb.");

Console.WriteLine();

// Ignore inherited methods.

MethodInfo[] mi = t.GetMethods(BindingFlags.DeclaredOnly |

BindingFlags.Instance |

BindingFlags.Public) ;

// Invoke each method.

foreach(MethodInfo m in mi) {

Console.WriteLine("Calling {0} ", m.Name);

// Get the parameters.

ParameterInfo[] pi = m.GetParameters();

// Execute methods.

switch(pi.Length) {

case 0: // no args

if(m.ReturnType == typeof(int)) {

val = (int) m.Invoke(reflectOb, null);

Console.WriteLine("Result is " + val);

}

else if(m.ReturnType == typeof(void)) {

m.Invoke(reflectOb, null);

}

break;

case 1: // one arg

if(pi[0].ParameterType == typeof(int)) {

object[] args = new object[1];

args[0] = 14;

if((bool) m.Invoke(reflectOb, args))

Console.WriteLine("14 is between x and y");

else

Console.WriteLine("14 is not between x and y");

}

break;

case 2: // two args

if((pi[0].ParameterType == typeof(int)) &&

(pi[1].ParameterType == typeof(int))) {

object[] args = new object[2];

args[0] = 9;

args[1] = 18;

m.Invoke(reflectOb, args);

}

else if((pi[0].ParameterType == typeof(double)) &&

(pi[1].ParameterType == typeof(double))) {

object[] args = new object[2];

args[0] = 1.12;

args[1] = 23.4;

m.Invoke(reflectOb, args);

}

break;

}

Console.WriteLine();

}

}

}

listing 11

[AttributeUsage(AttributeTargets.All)]

public class RemarkAttribute : Attribute {

string pri_remark; // underlies remark property

public RemarkAttribute(string comment) {

pri_remark = comment;

}

public string remark {

get {

return pri_remark;

}

}

}

listing 12

// A simple attribute example.

using System;

using System.Reflection;

[AttributeUsage(AttributeTargets.All)]

public class RemarkAttribute : Attribute {

string pri_remark; // underlies remark property

public RemarkAttribute(string comment) {

pri_remark = comment;

}

public string remark {

get {

return pri_remark;

}

}

}

[RemarkAttribute("This class uses an attribute.")]

class UseAttrib {

// ...

}

class AttribDemo {

public static void Main() {

Type t = typeof(UseAttrib);

Console.Write("Attributes in " + t.Name + ": ");

object[] attribs = t.GetCustomAttributes(false);

foreach(object o in attribs) {

Console.WriteLine(o);

}

Console.Write("Remark: ");

// Retrieve the RemarkAttribute.

Type tRemAtt = typeof(RemarkAttribute);

RemarkAttribute ra = (RemarkAttribute)

Attribute.GetCustomAttribute(t, tRemAtt);

Console.WriteLine(ra.remark);

}

}

listing 13

[AttributeUsage(AttributeTargets.All)]

public class RemarkAttribute : Attribute {

string pri_remark; // underlies remark property

public string supplement; // this is a named parameter

public RemarkAttribute(string comment) {

pri_remark = comment;

supplement = "None";

}

public string remark {

get {

return pri_remark;

}

}

}

listing 14

// Use a named attribute parameter.

using System;

using System.Reflection;

[AttributeUsage(AttributeTargets.All)]

public class RemarkAttribute : Attribute {

string pri_remark; // underlies remark property

public string supplement; // this is a named parameter

public RemarkAttribute(string comment) {

pri_remark = comment;

supplement = "None";

}

public string remark {

get {

return pri_remark;

}

}

}

[RemarkAttribute("This class uses an attribute.",

supplement = "This is additional info.")]

class UseAttrib {

// ...

}

class NamedParamDemo {

public static void Main() {

Type t = typeof(UseAttrib);

Console.Write("Attributes in " + t.Name + ": ");

object[] attribs = t.GetCustomAttributes(false);

foreach(object o in attribs) {

Console.WriteLine(o);

}

// Retrieve the RemarkAttribute.

Type tRemAtt = typeof(RemarkAttribute);

RemarkAttribute ra = (RemarkAttribute)

Attribute.GetCustomAttribute(t, tRemAtt);

Console.Write("Remark: ");

Console.WriteLine(ra.remark);

Console.Write("Supplement: ");

Console.WriteLine(ra.supplement);

}

}

listing 15

// Use a property as a named attribute parameter.

using System;

using System.Reflection;

[AttributeUsage(AttributeTargets.All)]

public class RemarkAttribute : Attribute {

string pri_remark; // underlies remark property

int pri_priority; // underlies priority property

public string supplement; // this is a named parameter

public RemarkAttribute(string comment) {

pri_remark = comment;

supplement = "None";

}

public string remark {

get {

return pri_remark;

}

}

// Use a property as a named parameter.

public int priority {

get {

return pri_priority;

}

set {

pri_priority = value;

}

}

}

[RemarkAttribute("This class uses an attribute.",

supplement = "This is additional info.",

priority = 10)]

class UseAttrib {

// ...

}

class NamedParamDemo {

public static void Main() {

Type t = typeof(UseAttrib);

Console.Write("Attributes in " + t.Name + ": ");

object[] attribs = t.GetCustomAttributes(false);

foreach(object o in attribs) {

Console.WriteLine(o);

}

// Retrieve the RemarkAttribute.

Type tRemAtt = typeof(RemarkAttribute);

RemarkAttribute ra = (RemarkAttribute)

Attribute.GetCustomAttribute(t, tRemAtt);

Console.Write("Remark: ");

Console.WriteLine(ra.remark);

Console.Write("Supplement: ");

Console.WriteLine(ra.supplement);

Console.WriteLine("Priority: " + ra.priority);

}

}

listing 16

// Demonstrate the Conditional attribute.

#define TRIAL

using System;

using System.Diagnostics;

class Test {

[Conditional("TRIAL")]

void trial() {

Console.WriteLine("Trial version, not for distribution.");

}

[Conditional("RELEASE")]

void release() {

Console.WriteLine("Final release version.");

}

public static void Main() {

Test t = new Test();

t.trial(); // call only if TRIAL is defined

t.release(); // called only if RELEASE is defined

}

}

listing 17

// Demonstrate the Obsolete attribute.

using System;

class Test {

[Obsolete("Use myMeth2, instead.")]

static int myMeth(int a, int b) {

return a / b;

}

// Improved version of myMeth.

static int myMeth2(int a, int b) {

return b == 0 ? 0 : a /b;

}

public static void Main() {

// warning displayed for this

Console.WriteLine("4 / 3 is " + Test.myMeth(4, 3));

// no warning here

Console.WriteLine("4 / 3 is " + Test.myMeth2(4, 3));

}

}

listing 1

// A simple generic class.

using System;

// In the following Gen class, T is a type

// parameter that will be replaced by a real

// type when an object of type Gen is created.

class Gen<T> {

T ob; // declare an object of type T

// Notice that this constructor has a parameter of type T.

public Gen(T o) {

ob = o;

}

// Return ob, which is of type T.

public T getob() {

return ob;

}

// Show type of T.

public void showType() {

Console.WriteLine("Type of T is " + typeof(T));

}

}

// Demonstrate the generic class.

class GenericsDemo {

public static void Main() {

// Create a Gen reference for int.

Gen<int> iOb;

// Create a Gen<int> object and assign its

// reference to iOb.

iOb = new Gen<int>(102);

// Show the type of data used by iOb.

iOb.showType();

// Get the value in iOb.

int v = iOb.getob();

Console.WriteLine("value: " + v);

Console.WriteLine();

// Create a Gen object for strings.

Gen<string> strOb = new Gen<string>("Generics add power.");

// Show the type of data stored in strOb.

strOb.showType();

// Get the value in strOb.

string str = strOb.getob();

Console.WriteLine("value: " + str);

}

}

listing 2

// NonGen is functionally equivalent to Gen

// but does not use generics.

using System;

class NonGen {

object ob; // ob is now of type object

// Pass the constructor a reference of

// type object.

public NonGen(object o) {

ob = o;

}

// Return type object.

public object getob() {

return ob;

}

// Show type of ob.

public void showType() {

Console.WriteLine("Type of ob is " + ob.GetType());

}

}

// Demonstrate the non-generic class.

class NonGenDemo {

public static void Main() {

NonGen iOb;

// Create NonGen object.

iOb = new NonGen(102);

// Show the type of data stored in iOb.

iOb.showType();

// Get the value in iOb.

// This time, a cast is necessary.

int v = (int) iOb.getob();

Console.WriteLine("value: " + v);

Console.WriteLine();

// Create another NonGen object and

// store a string in it.

NonGen strOb = new NonGen("Non-Generics Test");

// Show the type of data stored strOb.

strOb.showType();

// Get the value of strOb.

// Again, notice that a cast is necessary.

String str = (string) strOb.getob();

Console.WriteLine("value: " + str);

// This compiles, but is conceptually wrong!

iOb = strOb;

// The following line results in a run-time exception.

// v = (int) iOb.getob(); // run-time error!

}

}

listing 3

// A simple generic class with two type

// parameters: T and V.

using System;

class TwoGen<T, V> {

T ob1;

V ob2;

// Notice that this construtor has parameters

// of type T and V.

public TwoGen(T o1, V o2) {

ob1 = o1;

ob2 = o2;

}

// Show types of T and V.

public void showTypes() {

Console.WriteLine("Type of T is " + typeof(T));

Console.WriteLine("Type of V is " + typeof(V));

}

public T getob1() {

return ob1;

}

public V getob2() {

return ob2;

}

}

// Demonstrate two generic type parameters.

class SimpGen {

public static void Main() {

TwoGen<int, string> tgObj =

new TwoGen<int, string>(119, "Alpha Beta Gamma");

// Show the types.

tgObj.showTypes();

// Obtain and show values.

int v = tgObj.getob1();

Console.WriteLine("value: " + v);

string str = tgObj.getob2();

Console.WriteLine("value: " + str);

}

}

listing 4

// A simple demonstration of a base class constraint.

using System;

class A {

public void hello() {

Console.WriteLine("Hello");

}

}

// Class B inherits A.

class B : A { }

// Class C does not inherit A.

class C { }

// Because of the base class constraint, all type arguments

// passed to Test must have A as a base class.

class Test<T> where T : A {

T obj;

public Test(T o) {

obj = o;

}

public void sayHello() {

// OK to call hello() because it's declared

// by the base class A.

obj.hello();

}

}

class BaseClassConstraintDemo {

public static void Main() {

A a = new A();

B b = new B();

C c = new C();

// The following is valid because

// A is the specified base class.

Test<A> t1 = new Test<A>(a);

t1.sayHello();

// The following is valid because

// B inherits A.

Test<B> t2 = new Test<B>(b);

t2.sayHello();

// The following is invalid because

// C does not inherit A.

// Test<C> t3 = new Test<C>(c); // Error!

}

}

listing 5

// A more practical demonstration of a base class constraint.

using System;

// A custom exception that is thrown if a name or number

// is not found.

class NotFoundException : ApplicationException {}

// A base class that stores a name and phone number.

class PhoneNumber {

string name;

string number;

public PhoneNumber(string n, string num) {

name = n;

number = num;

}

public string Number {

get { return number; }

set { number = value; }

}

public string Name {

get { return name; }

set { name = value; }

}

}

// A class of phone numbers for friends.

class Friend : PhoneNumber {

bool isWorkNumber;

public Friend(string n, string num, bool wk) :

base(n, num)

{

isWorkNumber = wk;

}

public bool IsWorkNumber {

get {

return isWorkNumber;

}

}

// ...

}

// A class of phone numbers for suppliers.

class Supplier : PhoneNumber {

public Supplier(string n, string num) :

base(n, num) { }

// ...

}

// Notice that this class does not inherit PhoneNumber,

class EmailFriend {

// ...

}

// PhoneList can manage any type of phone list

// as long as it is derived from PhoneNumber.

class PhoneList<T> where T : PhoneNumber {

T[] phList;

int end;

public PhoneList() {

phList = new T[10];

end = 0;

}

public bool add(T newEntry) {

if(end == 10) return false;

phList[end] = newEntry;

end++;

return true;

}

// Given a name, find and return the phone info.

public T findByName(string name) {

for(int i=0; i<end; i++) {

// Name can be used because it is a member of

// PhoneNumber, which is the base class constraint.

if(phList[i].Name == name)

return phList[i];

}

// Name not in list.

throw new NotFoundException();

}

// Given a number, find and return the phone info.

public T findByNumber(string number) {

for(int i=0; i<end; i++) {

// Number can be used because it is also a member of

// PhoneNumber which, is the base class constraint.

if(phList[i].Number == number)

return phList[i];

}

// Number not in list.

throw new NotFoundException();

}

// ...

}

// Demonstrate base clas constraints.

class UseBaseClassConstraint {

public static void Main() {

// The following code is OK because Friend

// inherits PhoneNumber.

PhoneList<Friend> plist = new PhoneList<Friend>();

plist.add(new Friend("Tom", "555-1234", true));

plist.add(new Friend("Gary", "555-6756", true));

plist.add(new Friend("Matt", "555-9254", false));

try {

// Find the number of a friend given a name.

Friend frnd = plist.findByName("Gary");

Console.Write(frnd.Name + ": " + frnd.Number);

if(frnd.IsWorkNumber)

Console.WriteLine(" (work)");

else

Console.WriteLine();

} catch(NotFoundException) {

Console.WriteLine("Not Found");

}

Console.WriteLine();

// The following code is also OK because Supplier

// inherits PhoneNumber.

PhoneList<Supplier> plist2 = new PhoneList<Supplier>();

plist2.add(new Supplier("Global Hardware", "555-8834"));

plist2.add(new Supplier("Computer Warehouse", "555-9256"));

plist2.add(new Supplier("NetworkCity", "555-2564"));

try {

// Find the name of a supplier given a number

Supplier sp = plist2.findByNumber("555-2564");

Console.WriteLine(sp.Name + ": " + sp.Number);

} catch(NotFoundException) {

Console.WriteLine("Not Found");

}

// The following declaration is invalid

// because EmailFriend does NOT inherit PhoneNumber.

// PhoneList<EmailFriend> plist3 =

// new PhoneList<EmailFriend>(); // Error!

}

}

listing 6

// Use an interface constraint.

using System;

// A custom exception that is thrown if a name or number

// is not found.

class NotFoundException : ApplicationException { }

// An interface that supports a name and phone number.

public interface IPhoneNumber {

string Number {

get;

set;

}

string Name {

get;

set;

}

}

// A class of phone numbers for friends.

// It implements IPhoneNumber.

class Friend : IPhoneNumber {

string name;

string number;

bool isWorkNumber;

public Friend(string n, string num, bool wk) {

name = n;

number = num;

isWorkNumber = wk;

}

public bool IsWorkNumber {

get {

return isWorkNumber;

}

}

// Implement IPhoneNumber

public string Number {

get { return number; }

set { number = value; }

}

public string Name {

get { return name; }

set { name = value; }

}

// ...

}

// A class of phone numbers for suppliers.

class Supplier : IPhoneNumber {

string name;

string number;

public Supplier(string n, string num) {

name = n;

number = num;

}

// Implement IPhoneNumber

public string Number {

get { return number; }

set { number = value; }

}

public string Name {

get { return name; }

set { name = value; }

}

// ...

}

// Notice that this class does not implement IPhoneNumber,

class EmailFriend {

// ...

}

// PhoneList can manage any type of phone list

// as long as it is implements IPhoneNumber.

class PhoneList<T> where T : IPhoneNumber {

T[] phList;

int end;

public PhoneList() {

phList = new T[10];

end = 0;

}

public bool add(T newEntry) {

if(end == 10) return false;

phList[end] = newEntry;

end++;

return true;

}

// Given a name, find and return the phone info.

public T findByName(string name) {

for(int i=0; i<end; i++) {

// Name can be used because it is a member of

// IPhoneNumber, which is the interface constraint.

if(phList[i].Name == name)

return phList[i];

}

// Name not in list.

throw new NotFoundException();

}

// Given a number, find and return the phone info.

public T findByNumber(string number) {

for(int i=0; i<end; i++) {

// Number can be used becasue it is also a member of

// IPhoneNumber, which is the interface constraint.

if(phList[i].Number == number)

return phList[i];

}

// Number not in list.

throw new NotFoundException();

}

// ...

}

// Demonstrate interface constraints.

class UseInterfaceConstraint {

public static void Main() {

// The following code is OK because Friend

// implements IPhoneNumber.

PhoneList<Friend> plist = new PhoneList<Friend>();

plist.add(new Friend("Tom", "555-1234", true));

plist.add(new Friend("Gary", "555-6756", true));

plist.add(new Friend("Matt", "555-9254", false));

try {

// Find the number of a friend given a name.

Friend frnd = plist.findByName("Gary");

Console.Write(frnd.Name + ": " + frnd.Number);

if(frnd.IsWorkNumber)

Console.WriteLine(" (work)");

else

Console.WriteLine();

} catch(NotFoundException) {

Console.WriteLine("Not Found");

}

Console.WriteLine();

// The following code is also OK because Supplier

// implements IPhoneNumber.

PhoneList<Supplier> plist2 = new PhoneList<Supplier>();

plist2.add(new Supplier("Global Hardware", "555-8834"));

plist2.add(new Supplier("Computer Warehouse", "555-9256"));

plist2.add(new Supplier("NetworkCity", "555-2564"));

try {

// Find the name of a supplier given a number

Supplier sp = plist2.findByNumber("555-2564");

Console.WriteLine(sp.Name + ": " + sp.Number);

} catch(NotFoundException) {

Console.WriteLine("Not Found");

}

// The following declaration is invalid

// because EmailFriend does NOT implement IPhoneNumber.

// PhoneList<EmailFriend> plist3 =

// new PhoneList<EmailFriend>(); // Error!

}

}

listing 7

// Demonstrate a new() constructor constraint.

using System;

class MyClass {

public MyClass() {

// ...

}

//...

}

class Test<T> where T : new() {

T obj;

public Test() {

// This works because of the new() constraint.

obj = new T(); // create a T object

}

// ...

}

class ConsConstraintDemo {

public static void Main() {

Test<MyClass> x = new Test<MyClass>();

}

}

listing 8

// Demonstrate a reference constriant.

using System;

class MyClass {

//...

}

// Use a reference constraint.

class Test<T> where T : class {

T obj;

public Test() {

// The following statement is legal only

// because T is guaranteed to be a reference

// type, which can be assigned the value null.

obj = null;

}

// ...

}

class ClassConstraintDemo {

public static void Main() {

// The following is OK because MyClass is a class.

Test<MyClass> x = new Test<MyClass>();

// The next line is in error because int is

// a value type.

// Test<int> y = new Test<int>();

}

}

listing 9

// Demonstrate a value type constriant.

using System;

struct MyStruct {

//...

}

class MyClass {

// ...

}

class Test<T> where T : struct {

T obj;

public Test(T x) {

obj = x;

}

// ...

}

class ValueConstraintDemo {

public static void Main() {

// Both of these declarations are legal.

Test<MyStruct> x = new Test<MyStruct>(new MyStruct());

Test<int> y = new Test<int>(10);

// But, the following declaration is illegal!

// Test<MyClass> z = new Test<MyClass>(new MyClass());

}

}

listing 10

// Create relationship between two type parameters.

using System;

class A {

//...

}

class B : A {

// ...

}

// Here, V must inherit T.

class Gen<T, V> where V : T {

// ...

}

class NakedConstraintDemo {

public static void Main() {

// This declaration is OK because B inherits A.

Gen<A, B> x = new Gen<A, B>();

// This declaration is in error because

// A does not inherit B.

// Gen<B, A> y = new Gen<B, A>();

}

}

listing 11

// Use multiple where clauses.

using System;

// Gen has two type arguments and both have

// a where clause.

class Gen<T, V> where T : class

where V : struct {

T ob1;

V ob2;

public Gen(T t, V v) {

ob1 = t;

ob2 = v;

}

}

class MultipleConstraintDemo {

public static void Main() {

// This is OK because string is a class and

// int is a value type.

Gen<string, int> obj = new Gen<string, int>("test", 11);

// The next line is wrong because bool is not

// a reference type.

// Gen<bool, int> obj = new Gen<bool, int>(true, 11);

}

}

listing 12

// Demonstrate the default keyword.

using System;

class MyClass {

//...

}

// Construct a default object of T.

class Test<T> {

public T obj;

public Test() {

// The following statement would work

// only for reference types.

// obj = null;

// This statement works for both

// reference and value types.

obj = default(T);

}

// ...

}

class DefaultDemo {

public static void Main() {

// Construct Test using a reference type.

Test<MyClass> x = new Test<MyClass>();

if(x.obj == null)

Console.WriteLine("x.obj is null.");

// Construct Test using a value type.

Test<int> y = new Test<int>();

if(y.obj == 0)

Console.WriteLine("y.obj is 0.");

}

}

listing 13

// Demonstrate a generic struct.

using System;

// This structure is generic.

struct XY<T> {

T x;

T y;

public XY(T a, T b) {

x = a;

y = b;

}

public T X {

get { return x; }

set { x = value; }

}

public T Y {

get { return y; }

set { y = value; }

}

}

class StructTest {

public static void Main() {

XY<int> xy = new XY<int>(10, 20);

XY<double> xy2 = new XY<double>(88.0, 99.0);

Console.WriteLine(xy.X + ", " + xy.Y);

Console.WriteLine(xy2.X + ", " + xy2.Y);

}

}

listing 14

// Demonstrate a generic method.

using System;

// A class of array utilities. Notice that this is not

// a generic class.

class ArrayUtils {

// Copy an array, inserting a new element

// in the process. This is a generic method.

public static bool copyInsert<T>(T e, int idx,

T[] src, T[] target) {

// See if target array is big enough.

if(target.Length < src.Length+1)

return false;

// Copy src to target, inserting e at idx in the proecess.

for(int i=0, j=0; i < src.Length; i++, j++) {

if(i == idx) {

target[j] = e;

j++;

}

target[j] = src[i];

}

return true;

}

}

class GenMethDemo {

public static void Main() {

int[] nums = { 1, 2, 3 };

int[] nums2 = new int[4];

// Display contents of nums.

Console.Write("Contents of nums: ");

foreach(int x in nums)

Console.Write(x + " ");

Console.WriteLine();

// Operate on an int array.

ArrayUtils.copyInsert(99, 2, nums, nums2);

// Display contents of nums2.

Console.Write("Contents of nums2: ");

foreach(int x in nums2)

Console.Write(x + " ");

Console.WriteLine();

// Now, use copyInsert on an array of strings.

string[] strs = { "Generics", "are", "powerful."};

string[] strs2 = new string[4];

// Display contents of strs.

Console.Write("Contents of strs: ");

foreach(string s in strs)

Console.Write(s + " ");

Console.WriteLine();

// Insert into a string array.

ArrayUtils.copyInsert("in C#", 1, strs, strs2);

// Display contents of strs2.

Console.Write("Contents of strs2: ");

foreach(string s in strs2)

Console.Write(s + " ");

Console.WriteLine();

// This call is invalid because the first argument

// if of type double, and the third and fourth arguments

// have base types of int.

// ArrayUtils.copyInsert(0.01, 2, nums, nums2);

}

}

listing 15

// A simple generic delegate.

using System;

// Declare a generic delegate.

delegate T SomeOp<T>(T v);

class GenDelegateDemo {

// Return the summation of the argument.

static int sum(int v) {

int result = 0;

for(int i=v; i>0; i--)

result += i;

return result;

}

// Return a string containing the reverse of the argument.

static string reflect(string str) {

string result = "";

foreach(char ch in str)

result = ch + result;

return result;

}

public static void Main() {

// Construct an int delegate. Notice use of method group

// conversion on generic delegate.

SomeOp<int> intDel = sum;

Console.WriteLine(intDel(3));

// Construct a string delegate. Also use method group conversion.

SomeOp<string> strDel = reflect;

Console.WriteLine(strDel("Hello"));

}

}

listing 16

// Convert event example from Chapter 15 to

// use generic delegate.

using System;

// Derive a class from EventArgs.

class MyEventArgs : EventArgs {

public int eventnum;

}

// Declare a generic delegate for an event.

delegate void MyEventHandler<T, V>(T source, V args);

// Declare an event class.

class MyEvent {

static int count = 0;

public event MyEventHandler<MyEvent, MyEventArgs> SomeEvent;

// This fires SomeEvent.

public void OnSomeEvent() {

MyEventArgs arg = new MyEventArgs();

if(SomeEvent != null) {

arg.eventnum = count++;

SomeEvent(this, arg);

}

}

}

class X {

public void handler<T, V>(T source, V arg) where V : MyEventArgs {

Console.WriteLine("Event " + arg.eventnum +

" received by an X object.");

Console.WriteLine("Source is " + source);

Console.WriteLine();

}

}

class Y {

public void handler<T,V>(T source, V arg) where V : MyEventArgs {

Console.WriteLine("Event " + arg.eventnum +

" received by a Y object.");

Console.WriteLine("Source is " + source);

Console.WriteLine();

}

}

class UseGenericEventDelegate {

public static void Main() {

X ob1 = new X();

Y ob2 = new Y();

MyEvent evt = new MyEvent();

// Add handler() to the event list.

evt.SomeEvent += ob1.handler;

evt.SomeEvent += ob2.handler;

// Fire the event.

evt.OnSomeEvent();

evt.OnSomeEvent();

}

}

listing 17

// Demonstrate a generic interface.

using System;

public interface ISeries<T> {

T getNext(); // return next element in series

void reset(); // restart the series

void setStart(T v); // set the starting element

}

// Implement ISeries.

class ByTwos<T> : ISeries<T> {

T start;

T val;

// This delegate defines the form of a method

// that will be called when the next element in

// the series is needed.

public delegate T IncByTwo(T v);

// This delegate reference will be assigned the

// method passed to the ByTwos constructor.

IncByTwo incr;

public ByTwos(IncByTwo incrMeth) {

start = default(T);

val = default(T);

incr = incrMeth;

}

public T getNext() {

val = incr(val);

return val;

}

public void reset() {

val = start;

}

public void setStart(T v) {

start = v;

val = start;

}

}

class ThreeD {

public int x, y, z;

public ThreeD(int a, int b, int c) {

x = a;

y = b;

z = c;

}

}

class GenIntfDemo {

// Define plus two for int.

static int intPlusTwo(int v) {

return v + 2;

}

// Define plus two for double.

static double doublePlusTwo(double v) {

return v + 2.0;

}

// Define plus two for ThreeD.

static ThreeD ThreeDPlusTwo(ThreeD v) {

if(v==null) return new ThreeD(0, 0, 0);

else return new ThreeD(v.x + 2, v.y + 2, v.z + 2);

}

public static void Main() {

// Demonstrate int series.

ByTwos<int> intBT = new ByTwos<int>(intPlusTwo);

for(int i=0; i < 5; i++)

Console.Write(intBT.getNext() + " ");

Console.WriteLine();

// Demonstrate double series.

ByTwos<double> dblBT = new ByTwos<double>(doublePlusTwo);

dblBT.setStart(11.4);

for(int i=0; i < 5; i++)

Console.Write(dblBT.getNext() + " ");

Console.WriteLine();

// Demonstrate ThreeD series.

ByTwos<ThreeD> ThrDBT = new ByTwos<ThreeD>(ThreeDPlusTwo);

ThreeD coord;

for(int i=0; i < 5; i++) {

coord = ThrDBT.getNext();

Console.Write(coord.x + "," +

coord.y + "," +

coord.z + " ");

}

Console.WriteLine();

}

}

listing 18

// This won't work!

public static bool isIn<T>(T what, T[] obs) {

foreach(T v in obs)

if(v == what) // Error!

return true;

return false;

}

listing 19

// Demonstrate IComparable.

using System;

class MyClass : IComparable {

public int val;

public MyClass(int x) { val = x; }

// Implement IComparable.

public int CompareTo(object obj) {

return val - ((MyClass) obj).val;

}

}

class CompareDemo {

// Require IComparable interface.

public static bool isIn<T>(T what, T[] obs) where T : IComparable {

foreach(T v in obs)

if(v.CompareTo(what) == 0) // now OK, uses CompareTo()

return true;

return false;

}

// Demonstrate comparisons.

public static void Main() {

// Use isIn() with int.

int[] nums = { 1, 2, 3, 4, 5 };

if(isIn(2, nums))

Console.WriteLine("2 is found.");

if(isIn(99, nums))

Console.WriteLine("This won't display.");

// Use isIn() with string.

string[] strs = { "one", "two", "Three"};

if(isIn("two", strs))

Console.WriteLine("two is found.");

if(isIn("five", strs))

Console.WriteLine("This won't display.");

// Use isIn with MyClass.

MyClass[] mcs = { new MyClass(1), new MyClass(2),

new MyClass(3), new MyClass(4) };

if(isIn(new MyClass(3), mcs))

Console.WriteLine("MyClass(3) is found.");

if(isIn(new MyClass(99), mcs))

Console.WriteLine("This won't display.");

}

}

listing 20

// This version of MyClass implements IComparable<T>

class MyClass : IComparable<MyClass> {

public int val;

public MyClass(int x) { val = x; }

public int CompareTo(MyClass obj) {

return val - obj.val; // Now, no cast is needed.

}

}

listing 21

// A simple generic class hierarchy.

using System;

// A generic base class.

class Gen<T> {

T ob;

public Gen(T o) {

ob = o;

}

// Return ob.

public T getob() {

return ob;

}

}

// A class derived from Gen.

class Gen2<T> : Gen<T> {

public Gen2(T o) : base(o) {

// ...

}

}

class GenHierDemo {

public static void Main() {

Gen2<string> g2 = new Gen2<string>("Hello");

Console.WriteLine(g2.getob());

}

}

listing 22

// A derived class can add its own type parameters.

using System;

// A generic base class.

class Gen<T> {

T ob; // declare an object of type T

// Pass the constructor an object of

// type T.

public Gen(T o) {

ob = o;

}

// Return ob.

public T getob() {

return ob;

}

}

// A derived class of Gen that defines a second

// type parameter, called V.

class Gen2<T, V> : Gen<T> {

V ob2;

public Gen2(T o, V o2) : base(o) {

ob2 = o2;

}

public V getob2() {

return ob2;

}

}

// Create an object of type Gen2.

class GenHierDemo2 {

public static void Main() {

// Create a Gen2 object for string and int.

Gen2<string, int> x =

new Gen2<string, int>("Value is: ", 99);

Console.Write(x.getob());

Console.WriteLine(x.getob2());

}

}

listing 23

// A nongeneric class can be the base class

// of a generic derived class.

using System;

// A nongeneric class.

class NonGen {

int num;

public NonGen(int i) {

num = i;

}

public int getnum() {

return num;

}

}

// A generic derived class.

class Gen<T> : NonGen {

T ob;

public Gen(T o, int i) : base (i) {

ob = o;

}

// Return ob.

public T getob() {

return ob;

}

}

// Create a Gen object.

class HierDemo3 {

public static void Main() {

// Create a Gen object for string.

Gen<String> w = new Gen<String>("Hello", 47);

Console.Write(w.getob() + " ");

Console.WriteLine(w.getnum());

}

}

listing 24

// Overriding a virtual method in a generic class.

using System;

// A generic base class.

class Gen<T> {

protected T ob;

public Gen(T o) {

ob = o;

}

// Return ob. This method is virtual.

public virtual T getob() {

Console.Write("Gen's getob(): " );

return ob;

}

}

// A derived class of Gen that overrides getob().

class Gen2<T> : Gen<T> {

public Gen2(T o) : base(o) { }

// Override getob().

public override T getob() {

Console.Write("Gen2's getob(): ");

return ob;

}

}

// Demonstrate generic method override.

class OverrideDemo {

public static void Main() {

// Create a Gen object for int.

Gen<int> iOb = new Gen<int>(88);

// This calls Gen's version of getob().

Console.WriteLine(iOb.getob());

// Now, create a Gen2 object and assign its

// reference to iOb (which is a Gen<int> variable).

iOb = new Gen2<int>(99);

// This calls Gen2's verison of getob().

Console.WriteLine(iOb.getob());

}

}

listing 25

// Ambiguity can result when overloading

// methods that use type parameters.

//

// This program will not compile.

using System;

// A generic class that contains a potentially

// ambiguous overload of the set() method.

class Gen<T, V> {

T ob1;

V ob2;

// ...

// In some cases, these two methods

// will not differ in their parameter types.

public void set(T o) {

ob1 = o;

}

public void set(V o) {

ob2 = o;

}

}

class AmbiguityDemo {

public static void Main() {

Gen<int, double> ok = new Gen<int, double>();

Gen<int, int> notOK = new Gen<int, int>();

ok.set(10); // is valid, types differ

notOK.set(10); // ambiguous, types are the same

}

}



listing 1

// Demonstrate pointers and unsafe.

using System;

class UnsafeCode {

// Mark Main as unsafe.

unsafe public static void Main() {

int count = 99;

int* p; // create an int pointer

p = &count; // put address of count into p

Console.WriteLine("Initial value of count is " + *p);

*p = 10; // assign 10 to count via p

Console.WriteLine("New value of count is " + *p);

}

}

listing 2

// Demonstrate fixed.

using System;

class Test {

public int num;

public Test(int i) { num = i; }

}

class FixedCode {

// Mark Main as unsafe.

unsafe public static void Main() {

Test o = new Test(19);

fixed (int* p = &o.num) { // use fixed to put address of o.num into p

Console.WriteLine("Initial value of o.num is " + *p);

*p = 10; // assign the to count via p

Console.WriteLine("New value of o.num is " + *p);

}

}

}

listing 3

// Demonstrate the effects of pointer arithmethic.

using System;

class PtrArithDemo {

unsafe public static void Main() {

int x;

int i;

double d;

int* ip = &i;

double* fp = &d;

Console.WriteLine("int double\n");

for(x=0; x < 10; x++) {

Console.WriteLine((uint) (ip) + " " +

(uint) (fp));

ip++;

fp++;

}

}

}

listing 4

// Demonstrate pointer comparison.

using System;

class PtrCompDemo {

unsafe public static void Main() {

int[] nums = new int[11];

int x;

// find the middle

fixed (int* start = &nums[0]) {

fixed(int* end = &nums[nums.Length-1]) {

for(x=0; start+x <= end-x; x++) ;

}

}

Console.WriteLine("Middle element is " + x);

}

}

listing 5

/* An array name with an index yields a pointer to the

start of the array. */

using System;

class PtrArray {

unsafe public static void Main() {

int[] nums = new int[10];

fixed(int* p = &nums[0], p2 = nums) {

if(p == p2)

Console.WriteLine("p and p2 point to same address.");

}

}

}

listing 6

// Index a pointer as if it were an array.

using System;

class PtrIndexDemo {

unsafe public static void Main() {

int[] nums = new int[10];

// index pointer

Console.WriteLine("Index pointer like array.");

fixed (int* p = nums) {

for(int i=0; i < 10; i++)

p[i] = i; // index pointer like array

for(int i=0; i < 10; i++)

Console.WriteLine("p[{0}]: {1} ", i, p[i]);

}

// use pointer arithmetic

Console.WriteLine("\nUse pointer arithmetic.");

fixed (int* p = nums) {

for(int i=0; i < 10; i++)

*(p+i) = i; // use pointer arithmetic

for(int i=0; i < 10; i++)

Console.WriteLine("*(p+{0}): {1} ", i, *(p+i));

}

}

}

listing 7

// Use fixed to get a pointer to the start of a string.

using System;

class FixedString {

unsafe public static void Main() {

string str = "this is a test";

// Point p to start of str.

fixed(char* p = str) {

// Display the contents of str via p.

for(int i=0; p[i] != 0; i++)

Console.Write(p[i]);

}

Console.WriteLine();

}

}

listing 8

using System;

class MultipleIndirect {

unsafe public static void Main() {

int x; // holds an int value

int* p; // holds an int pointer

int** q; // holds an pointer to an int pointer

x = 10;

p = &x; // put address of x into p

q = &p; // put address of p into q

Console.WriteLine(**q); // display the value of x

}

}

listing 9

// Demonstrate stackalloc.

using System;

class UseStackAlloc {

unsafe public static void Main() {

int* ptrs = stackalloc int[3];

ptrs[0] = 1;

ptrs[1] = 2;

ptrs[2] = 3;

for(int i=0; i < 3; i++)

Console.WriteLine(ptrs[i]);

}

}

listing 10

// Demonstrate a fixed-size buffer.

using System;

// Create a fixed size buffer.

unsafe struct FixedBankRecord {

public fixed byte name[80]; // create a fixed-size buffer

public double balance;

public long ID;

}

class FixedSizeBuffer {

// mark Main as unsafe

unsafe public static void Main() {

Console.WriteLine("Size of FixedBankRecord is " +

sizeof(FixedBankRecord));

}

}

listing 11

// Demonstrate a nullable type.

using System;

class NullableDemo {

public static void Main() {

int? count = null;

if(count.HasValue)

Console.WriteLine("count has this value: " + count.Value);

else

Console.WriteLine("count has no value");

count = 100;

if(count.HasValue)

Console.WriteLine("count has this value: " + count.Value);

else

Console.WriteLine("count has no value");

}

}

listing 12

// Use nullable objects in expressions.

using System;

class NullableDemo {

public static void Main() {

int? count = null;

int? result = null;

int incr = 10; // notice that incr is a non-nullable type

// result contains null, because count is null.

result = count + incr;

if(result.HasValue)

Console.WriteLine("result has this value: " + result.Value);

else

Console.WriteLine("result has no value");

// Now, count is given a value and result

// will contain a value.

count = 100;

result = count + incr;

if(result.HasValue)

Console.WriteLine("result has this value: " + result.Value);

else

Console.WriteLine("result has no value");

}

}

listing 13

// Using ??

using System;

class NullableDemo2 {

// Return a zero balance.

static double getZeroBal() {

Console.WriteLine("In getZeroBal().");

return 0.0;

}

public static void Main() {

double? balance = 123.75;

double currentBalance;

// Here, getZeroBal( ) is not called because balance

// contains a value.

currentBalance = balance ?? getZeroBal();

Console.WriteLine(currentBalance);

}

}

listing 14

partial class XY {

public XY(int a, int b) {

x = a;

y = b;

}

}

listing 15

partial class XY {

int x;

public int X {

get { return x; }

set { x = value; }

}

}

listing 16

partial class XY {

int y;

public int Y {

get { return y; }

set { y = value; }

}

}

listing 17

// Demonstrate partial class definitions.

using System;

class Test {

public static void Main() {

XY xy = new XY(1, 2);

Console.WriteLine(xy.X + "," + xy.Y);

}

}

listing 18

// Demonstrate readonly.

using System;

class MyClass {

public static readonly int SIZE = 10;

}

class DemoReadOnly {

public static void Main() {

int[] nums = new int[MyClass.SIZE];

for(int i=0; i<MyClass.SIZE; i++)

nums[i] = i;

foreach(int i in nums)

Console.Write(i + " ");

// MyClass.SIZE = 100; // Error!!! can't change

}

}

listing 19

// Demonstrate using statement.

using System;

using System.IO;

class UsingDemo {

public static void Main() {

StreamReader sr = new StreamReader("test.txt");

// Use object inside using statement.

using(sr) {

Console.WriteLine(sr.ReadLine());

sr.Close();

}

// Create StreamReader inside the using statement.

using(StreamReader sr2 = new StreamReader("test.txt")) {

Console.WriteLine(sr2.ReadLine());

sr2.Close();

}

}

}

listing 20

#include <stdlib.h>

int __declspec(dllexport) absMax(int a, int b) {

return abs(a) < abs(b) ? abs(b) : abs(a);

}

listing 21

using System;

using System.Runtime.InteropServices;

class ExternMeth {

// Here an extern method is declared.

[DllImport("ExtMeth.dll")]

public extern static int absMax(int a, int b);

public static void Main() {

// Use the extern method.

int max = absMax(-10, -20);

Console.WriteLine(max);

}

}

listing 22

using System;

namespace MyNS {

public class MyClass {

public MyClass() {

Console.WriteLine("Constructing from MyClass1.dll.");

}

}

}

listing 23

using System;

namespace MyNS {

public class MyClass {

public MyClass() {

Console.WriteLine("Constructing from MyClass2.dll.");

}

}

}

listing 24

// extern alias statements must be at the top of the file.

extern alias Asm1;

extern alias Asm2;

using System;

class Demo {

public static void Main() {

Asm1::MyNS.MyClass t = new Asm1::MyNS.MyClass();

Asm2::MyNS.MyClass t2 = new Asm2::MyNS.MyClass();

}

}

listing 1

// Implement the Pythagorean Theorem.

using System;

class Pythagorean {

public static void Main() {

double s1;

double s2;

double hypot;

string str;

Console.WriteLine("Enter length of first side: ");

str = Console.ReadLine();

s1 = Double.Parse(str);

Console.WriteLine("Enter length of second side: ");

str = Console.ReadLine();

s2 = Double.Parse(str);

hypot = Math.Sqrt(s1*s1 + s2*s2);

Console.WriteLine("Hypotenuse is " + hypot);

}

}

listing 2

/* Compute the initial investment needed to attain

a known future value given annual rate of return

and the time period in years. */

using System;

class InitialInvestment {

public static void Main() {

decimal InitInvest; // initial investment

decimal FutVal; // future value

double NumYears; // number of years

double IntRate; // annual rate of return as a decimal

string str;

Console.Write("Enter future value: ");

str = Console.ReadLine();

try {

FutVal = Decimal.Parse(str);

} catch(FormatException exc) {

Console.WriteLine(exc.Message);

return;

}

Console.Write("Enter interest rate (such as 0.085): ");

str = Console.ReadLine();

try {

IntRate = Double.Parse(str);

} catch(FormatException exc) {

Console.WriteLine(exc.Message);

return;

}

Console.Write("Enter number of years: ");

str = Console.ReadLine();

try {

NumYears = Double.Parse(str);

} catch(FormatException exc) {

Console.WriteLine(exc.Message);

return;

}

InitInvest = FutVal / (decimal) Math.Pow(IntRate+1.0, NumYears);

Console.WriteLine("Initial investment required: {0:C}",

InitInvest);

}

}

listing 3

// Manually create a decimal number.

using System;

class CreateDec {

public static void Main() {

decimal d = new decimal(12345, 0, 0, false, 2);

Console.WriteLine(d);

}

}

listing 4

// Demonstrate several Char methods.

using System;

class CharDemo {

public static void Main() {

string str = "This is a test. $23";

int i;

for(i=0; i < str.Length; i++) {

Console.Write(str[i] + " is");

if(Char.IsDigit(str[i]))

Console.Write(" digit");

if(Char.IsLetter(str[i]))

Console.Write(" letter");

if(Char.IsLower(str[i]))

Console.Write(" lowercase");

if(Char.IsUpper(str[i]))

Console.Write(" uppercase");

if(Char.IsSymbol(str[i]))

Console.Write(" symbol");

if(Char.IsSeparator(str[i]))

Console.Write(" separator");

if(Char.IsWhiteSpace(str[i]))

Console.Write(" whitespace");

if(Char.IsPunctuation(str[i]))

Console.Write(" punctuation");

Console.WriteLine();

}

Console.WriteLine("Original: " + str);

// Convert to upper case.

string newstr = "";

for(i=0; i < str.Length; i++)

newstr += Char.ToUpper(str[i]);

Console.WriteLine("Uppercased: " + newstr);

}

}

listing 5

// Sort an array and search for a value.

using System;

class SortDemo {

public static void Main() {

int[] nums = { 5, 4, 6, 3, 14, 9, 8, 17, 1, 24, -1, 0 };

// Display original order.

Console.Write("Original order: ");

foreach(int i in nums)

Console.Write(i + " ");

Console.WriteLine();

// Sort the array.

Array.Sort(nums);

// Display sorted order.

Console.Write("Sorted order: ");

foreach(int i in nums)

Console.Write(i + " ");

Console.WriteLine();

// Search for 14.

int idx = Array.BinarySearch(nums, 14);

Console.WriteLine("Index of 14 is " + idx);

}

}

listing 6

// Sort and search an array of objects.

using System;

class MyClass : IComparable<MyClass> {

public int i;

public MyClass(int x) { i = x; }

// Implement IComparable<MyClass>.

public int CompareTo(MyClass v) {

return i - v.i;

}

}

class SortDemo {

public static void Main() {

MyClass[] nums = new MyClass[5];

nums[0] = new MyClass(5);

nums[1] = new MyClass(2);

nums[2] = new MyClass(3);

nums[3] = new MyClass(4);

nums[4] = new MyClass(1);

// Display original order.

Console.Write("Original order: ");

foreach(MyClass o in nums)

Console.Write(o.i + " ");

Console.WriteLine();

// Sort the array.

Array.Sort(nums);

// Display sorted order.

Console.Write("Sorted order: ");

foreach(MyClass o in nums)

Console.Write(o.i + " ");

Console.WriteLine();

// Search for MyClass(2).

MyClass x = new MyClass(2);

int idx = Array.BinarySearch(nums, x);

Console.WriteLine("Index of MyClass(2) is " + idx);

}

}

listing 7

// Reverse an array.

using System;

class ReverseDemo {

public static void Main() {

int[] nums = { 1, 2, 3, 4, 5 };

// Display original order.

Console.Write("Original order: ");

foreach(int i in nums)

Console.Write(i + " ");

Console.WriteLine();

// Reverse the entire array.

Array.Reverse(nums);

// Display reversed order.

Console.Write("Reversed order: ");

foreach(int i in nums)

Console.Write(i + " ");

Console.WriteLine();

// Reverse a range.

Array.Reverse(nums, 1, 3);

// Display reversed order.

Console.Write("Range reversed: ");

foreach(int i in nums)

Console.Write(i + " ");

Console.WriteLine();

}

}

listing 8

// Copy an array.

using System;

class CopyDemo {

public static void Main() {

int[] source = { 1, 2, 3, 4, 5 };

int[] target = { 11, 12, 13, 14, 15 };

int[] source2 = { -1, -2, -3, -4, -5 };

// Display source.

Console.Write("source: ");

foreach(int i in source)

Console.Write(i + " ");

Console.WriteLine();

// Display original target.

Console.Write("Original contents of target: ");

foreach(int i in target)

Console.Write(i + " ");

Console.WriteLine();

// Copy the entire array.

Array.Copy(source, target, source.Length);

// Display copy.

Console.Write("target after copy: ");

foreach(int i in target)

Console.Write(i + " ");

Console.WriteLine();

// Copy into middle of target.

Array.Copy(source2, 2, target, 3, 2);

// Display copy.

Console.Write("target after copy: ");

foreach(int i in target)

Console.Write(i + " ");

Console.WriteLine();

}

}

listing 9

// Demonstrate Predicate delegate.

using System;

class PredDemo {

// A predicate method.

// Returns true if v is negative.

static bool isNeg(int v) {

if(v < 0) return true;

return false;

}

public static void Main() {

int[] nums = { 1, 4, -1, 5, -9 };

Console.Write("Contents of nums: ");

foreach(int i in nums)

Console.Write(i + " ");

Console.WriteLine();

// First see if nums contains a negative value.

if(Array.Exists(nums, PredDemo.isNeg)) {

Console.WriteLine("nums contains a negative value.");

// Now, find first negative value.

int x = Array.Find(nums, PredDemo.isNeg);

Console.WriteLine("First negative value is : " + x);

}

else

Console.WriteLine("nums contains no negative values.");

}

}

listing 10

// Demonstrate an Action

using System;

class MyClass {

public int i;

public MyClass(int x) { i = x; }

}

class ActionDemo {

// An Action method.

// Displays the value it is passed.

static void show(MyClass o) {

Console.Write(o.i + " ");

}

// Another Action method.

// Negates the value it is passed.

static void neg(MyClass o) {

o.i = -o.i;

}

public static void Main() {

MyClass[] nums = new MyClass[5];

nums[0] = new MyClass(5);

nums[1] = new MyClass(2);

nums[2] = new MyClass(3);

nums[3] = new MyClass(4);

nums[4] = new MyClass(1);

Console.Write("Contents of nums: ");

// Use action to show the values.

Array.ForEach(nums, ActionDemo.show);

Console.WriteLine();

// Use action to negate the values.

Array.ForEach(nums, ActionDemo.neg);

Console.Write("Contents of nums negated: ");

// Use action to negate the values again.

Array.ForEach(nums, ActionDemo.show);

Console.WriteLine();

}

}

listing 11

// An automated pair of dice.

using System;

class RandDice {

public static void Main() {

Random ran = new Random();

Console.Write(ran.Next(1, 7) + " ");

Console.WriteLine(ran.Next(1, 7));

}

}

listing 12

// Demonstrate ICloneable.

using System;

class X {

public int a;

public X(int x) { a = x; }

}

class Test : ICloneable {

public X o;

public int b;

public Test(int x, int y) {

o = new X(x);

b = y;

}

public void show(string name) {

Console.Write(name + " values are ");

Console.WriteLine("o.a: {0}, b: {1}", o.a, b);

}

// Make a deep copy of the invoking object.

public object Clone() {

Test temp = new Test(o.a, b);

return temp;

}

}

class CloneDemo {

public static void Main() {

Test ob1 = new Test(10, 20);

ob1.show("ob1");

Console.WriteLine("Make ob2 a clone of ob1.");

Test ob2 = (Test) ob1.Clone();

ob2.show("ob2");

Console.WriteLine("Changing ob1.o.a to 99 and ob1.b to 88.");

ob1.o.a = 99;

ob1.b = 88;

ob1.show("ob1");

ob2.show("ob2");

}

}

listing 1

// Compare strings.

using System;

class CompareDemo {

public static void Main() {

string str1 = "one";

string str2 = "one";

string str3 = "ONE";

string str4 = "two";

string str5 = "one, too";

if(String.Compare(str1, str2) == 0)

Console.WriteLine(str1 + " and " + str2 +

" are equal.");

else

Console.WriteLine(str1 + " and " + str2 +

" are not equal.");

if(String.Compare(str1, str3) == 0)

Console.WriteLine(str1 + " and " + str3 +

" are equal.");

else

Console.WriteLine(str1 + " and " + str3 +

" are not equal.");

if(String.Compare(str1, str3, true) == 0)

Console.WriteLine(str1 + " and " + str3 +

" are equal ignoring case.");

else

Console.WriteLine(str1 + " and " + str3 +

" are not equal ignoring case.");

if(String.Compare(str1, str5) == 0)

Console.WriteLine(str1 + " and " + str5 +

" are equal.");

else

Console.WriteLine(str1 + " and " + str5 +

" are not equal.");

if(String.Compare(str1, 0, str5, 0, 3) == 0)

Console.WriteLine("First part of " + str1 + " and " +

str5 + " are equal.");

else

Console.WriteLine("First part of " + str1 + " and " +

str5 + " are not equal.");

int result = String.Compare(str1, str4);

if(result < 0)

Console.WriteLine(str1 + " is less than " + str4);

else if(result > 0)

Console.WriteLine(str1 + " is greater than " + str4);

else

Console.WriteLine(str1 + " equals " + str4);

}

}

listing 2

// Compare strings using StringComparison enumeration.

using System;

class StrCompDemo {

public static void Main() {

string pswd = "we~23&blx$";

string str;

Console.WriteLine("Enter password: ");

str = Console.ReadLine();

// Compare using invariant culture.

if(String.Compare(pswd, str,

StringComparison.InvariantCulture) == 0)

Console.WriteLine("Password accepted.");

else

Console.WriteLine("Password invalid.");

}

}

listing 3

// Demonstrate Concat().

using System;

class ConcatDemo {

public static void Main() {

string result = String.Concat("This ", "is ", "a ",

"test ", "of ", "the ",

"String ", "class.");

Console.WriteLine("result: " + result);

}

}

listing 4

// Demonstrate the object form of Concat().

using System;

class MyClass {

public static int count = 0;

public MyClass() { count++; }

}

class ConcatDemo {

public static void Main() {

string result = String.Concat("The value is " + 19);

Console.WriteLine("result: " + result);

result = String.Concat("hello ", 88, " ", 20.0, " ",

false, " ", 23.45M);

Console.WriteLine("result: " + result);

MyClass mc = new MyClass();

result = String.Concat(mc, " current count is ",

MyClass.count);

Console.WriteLine("result: " + result);

}

}

listing 5

// Search strings.

using System;

class StringSearchDemo {

public static void Main() {

string str = "C# has powerful string handling.";

int idx;

Console.WriteLine("str: " + str);

idx = str.IndexOf('h');

Console.WriteLine("Index of first 'h': " + idx);

idx = str.LastIndexOf('h');

Console.WriteLine("Index of last 'h': " + idx);

idx = str.IndexOf("ing");

Console.WriteLine("Index of first \"ing\": " + idx);

idx = str.LastIndexOf("ing");

Console.WriteLine("Index of last \"ing\": " + idx);

char[] chrs = { 'a', 'b', 'c' };

idx = str.IndexOfAny(chrs);

Console.WriteLine("Index of first 'a', 'b', or 'c': " + idx);

if(str.StartsWith("C# has"))

Console.WriteLine("str begins with \"C# has\"");

if(str.EndsWith("ling."))

Console.WriteLine("str ends with \"ling.\"");

}

}

listing 6

// Demonstrate Contains().

using System;

class ContainsDemo {

public static void Main() {

string str = "C# combines power with performance.";

if(str.Contains("power"))

Console.WriteLine("The sequence power was found.");

if(str.Contains("pow"))

Console.WriteLine("The sequence pow was found.");

if(!str.Contains("powerful"))

Console.WriteLine("The sequence powerful was not found.");

}

}

listing 7

// Split and join strings.

using System;

class SplitAndJoinDemo {

public static void Main() {

string str = "One if by land, two if by sea.";

char[] seps = {' ', '.', ',' };

// Split the string into parts.

string[] parts = str.Split(seps);

Console.WriteLine("Pieces from split: ");

for(int i=0; i < parts.Length; i++)

Console.WriteLine(parts[i]);

// Now, join the parts.

string whole = String.Join(" | ", parts);

Console.WriteLine("Result of join: ");

Console.WriteLine(whole);

}

}

listing 8

// Tokenize strings.

using System;

class TokenizeDemo {

public static void Main() {

string[] input = {

"100 + 19",

"100 / 3.3",

"-3 * 9",

"100 - 87"

};

char[] seps = {' '};

for(int i=0; i < input.Length; i++) {

// split string into parts

string[] parts = input[i].Split(seps);

Console.Write("Command: ");

for(int j=0; j < parts.Length; j++)

Console.Write(parts[j] + " ");

Console.Write(", Result: ");

double n = Double.Parse(parts[0]);

double n2 = Double.Parse(parts[2]);

switch(parts[1]) {

case "+":

Console.WriteLine(n + n2);

break;

case "-":

Console.WriteLine(n - n2);

break;

case "*":

Console.WriteLine(n * n2);

break;

case "/":

Console.WriteLine(n / n2);

break;

}

}

}

}

listing 9

// Trimming and padding.

using System;

class TrimPadDemo {

public static void Main() {

string str = "test";

Console.WriteLine("Original string: " + str);

// Pad on left with spaces.

str = str.PadLeft(10);

Console.WriteLine("|" + str + "|");

// Pad on right with spaces.

str = str.PadRight(20);

Console.WriteLine("|" + str + "|");

// Trim spaces.

str = str.Trim();

Console.WriteLine("|" + str + "|");

// Pad on left with #s.

str = str.PadLeft(10, '#');

Console.WriteLine("|" + str + "|");

// Pad on right with #s.

str = str.PadRight(20, '#');

Console.WriteLine("|" + str + "|");

// Trim #s.

str = str.Trim('#');

Console.WriteLine("|" + str + "|");

}

}

listing 10

// Inserting, replacing, and removing.

using System;

class InsRepRevDemo {

public static void Main() {

string str = "This test";

Console.WriteLine("Original string: " + str);

// Insert

str = str.Insert(5, "is a ");

Console.WriteLine(str);

// Replace string

str = str.Replace("is", "was");

Console.WriteLine(str);

// Replace characters

str = str.Replace('a', 'X');

Console.WriteLine(str);

// Remove

str = str.Remove(4, 5);

Console.WriteLine(str);

}

}

listing 11

// Use Substring().

using System;

class SubstringDemo {

public static void Main() {

string str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

Console.WriteLine("str: " + str);

Console.Write("str.Substring(15): ");

string substr = str.Substring(15);

Console.WriteLine(substr);

Console.Write("str.Substring(0, 15): ");

substr = str.Substring(0, 15);

Console.WriteLine(substr);

}

}

listing 12

// Demonstrate various format specifiers.

using System;

class FormatDemo {

public static void Main() {

double v = 17688.65849;

double v2 = 0.15;

int x = 21;

Console.WriteLine("{0:F2}", v);

Console.WriteLine("{0:N5}", v);

Console.WriteLine("{0:e}", v);

Console.WriteLine("{0:r}", v);

Console.WriteLine("{0:p}", v2);

Console.WriteLine("{0:X}", x);

Console.WriteLine("{0:D12}", x);

Console.WriteLine("{0:C}", 189.99);

}

}

listing 13

using System;

class FormatDemo2 {

public static void Main() {

// Format the same argument three different ways:

Console.WriteLine("{0:F2} {0:F3} {0:e}", 10.12345);

// Display arguments in non-sequential order.

Console.WriteLine("{2:d} {0:d} {1:d}", 1, 2, 3);

}

}

listing 14

// Use String.Format() to format a value.

using System;

class FormatDemo {

public static void Main() {

double v = 17688.65849;

double v2 = 0.15;

int x = 21;

string str = String.Format("{0:F2}", v);

Console.WriteLine(str);

str = String.Format("{0:N5}", v);

Console.WriteLine(str);

str = String.Format("{0:e}", v);

Console.WriteLine(str);

str = String.Format("{0:r}", v);

Console.WriteLine(str);

str = String.Format("{0:p}", v2);

Console.WriteLine(str);

str = String.Format("{0:X}", x);

Console.WriteLine(str);

str = String.Format("{0:D12}", x);

Console.WriteLine(str);

str = String.Format("{0:C}", 189.99);

Console.WriteLine(str);

}

}

listing 15

// A closer look at Format().

using System;

class FormatDemo2 {

public static void Main() {

int i;

int sum = 0;

int prod = 1;

string str;

/* Display the running sum and product

for the numbers 1 through 10. */

for(i=1; i <= 10; i++) {

sum += i;

prod *= i;

str = String.Format("Sum:{0,3:D} Product:{1,8:D}",

sum, prod);

Console.WriteLine(str);

}

}

}

listing 16

// Use ToString() to format values.

using System;

class ToStringDemo {

public static void Main() {

double v = 17688.65849;

double v2 = 0.15;

int x = 21;

string str = v.ToString("F2");

Console.WriteLine(str);

str = v.ToString("N5");

Console.WriteLine(str);

str = v.ToString("e");

Console.WriteLine(str);

str = v.ToString("r");

Console.WriteLine(str);

str = v2.ToString("p");

Console.WriteLine(str);

str = x.ToString("X");

Console.WriteLine(str);

str = x.ToString("D12");

Console.WriteLine(str);

str = 189.99.ToString("C");

Console.WriteLine(str);

}

}

listing 17

// Using custom formats.

using System;

class PictureFormatDemo {

public static void Main() {

double num = 64354.2345;

Console.WriteLine("Default format: " + num);

// Display with 2 decimal places.

Console.WriteLine("Value with two decimal places: " +

"{0:#.##}", num);

// Display with commas and 2 decimal places.

Console.WriteLine("Add commas: {0:#,###.##}", num);

// Display using scientific notation.

Console.WriteLine("Use scientific notation: " +

"{0:#.###e+00}", num);

// Scale the value by 1000.

Console.WriteLine("Value in 1,000s: " +

"{0:#0,}", num);

/* Display positive, negative, and zero

values differently. */

Console.WriteLine("Display positive, negative, " +

"and zero values differently.");

Console.WriteLine("{0:#.#;(#.##);0.00}", num);

num = -num;

Console.WriteLine("{0:#.##;(#.##);0.00}", num);

num = 0.0;

Console.WriteLine("{0:#.##;(#.##);0.00}", num);

// Display a percentage.

num = 0.17;

Console.WriteLine("Display a percentage: {0:#%}", num);

}

}

listing 18

// Format time and date information.

using System;

class TimeAndDateFormatDemo {

public static void Main() {

DateTime dt = DateTime.Now; // obtain current time

Console.WriteLine("d format: {0:d}", dt);

Console.WriteLine("D format: {0:D}", dt);

Console.WriteLine("t format: {0:t}", dt);

Console.WriteLine("T format: {0:T}", dt);

Console.WriteLine("f format: {0:f}", dt);

Console.WriteLine("F format: {0:F}", dt);

Console.WriteLine("g format: {0:g}", dt);

Console.WriteLine("G format: {0:G}", dt);

Console.WriteLine("m format: {0:m}", dt);

Console.WriteLine("M format: {0:M}", dt);

Console.WriteLine("r format: {0:r}", dt);

Console.WriteLine("R format: {0:R}", dt);

Console.WriteLine("s format: {0:s}", dt);

Console.WriteLine("u format: {0:u}", dt);

Console.WriteLine("U format: {0:U}", dt);

Console.WriteLine("y format: {0:y}", dt);

Console.WriteLine("Y format: {0:Y}", dt);

}

}

listing 19

// A simple clock.

using System;

class SimpleClock {

public static void Main() {

string t;

int seconds;

DateTime dt = DateTime.Now;

seconds = dt.Second;

for(;;) {

dt = DateTime.Now;

// update time if seconds change

if(seconds != dt.Second) {

seconds = dt.Second;

t = dt.ToString("T");

if(dt.Minute==0 && dt.Second==0)

t = t + "\a"; // ring bell at top of hour

Console.WriteLine(t);

}

}

}

}

listing 20

// Format time and date information.

using System;

class CustomTimeAndDateFormatsDemo {

public static void Main() {

DateTime dt = DateTime.Now;

Console.WriteLine("Time is {0:hh:mm tt}", dt);

Console.WriteLine("24 hour time is {0:HH:mm}", dt);

Console.WriteLine("Date is {0:ddd MMM dd, yyyy}", dt);

Console.WriteLine("Era: {0:gg}", dt);

Console.WriteLine("Time with seconds: " +

"{0:HH:mm:ss tt}", dt);

Console.WriteLine("Use m for day of month: {0:m}", dt);

Console.WriteLine("use m for minutes: {0:%m}", dt);

}

}

listing 21

// Format an enumeration.

using System;

class EnumFmtDemo {

enum Direction { North, South, East, West }

[Flags] enum Status { Ready=0x1, OffLine=0x2,

Waiting=0x4, TransmitOK=0x8,

RecieveOK=0x10, OnLine=0x20 }

public static void Main() {

Direction d = Direction.West;

Console.WriteLine("{0:G}", d);

Console.WriteLine("{0:F}", d);

Console.WriteLine("{0:D}", d);

Console.WriteLine("{0:X}", d);

Status s = Status.Ready | Status.TransmitOK;

Console.WriteLine("{0:G}", s);

Console.WriteLine("{0:F}", s);

Console.WriteLine("{0:D}", s);

Console.WriteLine("{0:X}", s);

}

}

listing 1

// Create a thread of execution.

using System;

using System.Threading;

class MyThread {

public int count;

string thrdName;

public MyThread(string name) {

count = 0;

thrdName = name;

}

// Entry point of thread.

public void run() {

Console.WriteLine(thrdName + " starting.");

do {

Thread.Sleep(500);

Console.WriteLine("In " + thrdName +

", count is " + count);

count++;

} while(count < 10);

Console.WriteLine(thrdName + " terminating.");

}

}

class MultiThread {

public static void Main() {

Console.WriteLine("Main thread starting.");

// First, construct a MyThread object.

MyThread mt = new MyThread("Child #1");

// Next, construct a thread from that object.

Thread newThrd = new Thread(new ThreadStart(mt.run));

// Finally, start execution of the thread.

newThrd.Start();

do {

Console.Write(".");

Thread.Sleep(100);

} while (mt.count != 10);

Console.WriteLine("Main thread ending.");

}

}

listing 2

// An alternate way to start a thread.

using System;

using System.Threading;

class MyThread {

public int count;

public Thread thrd;

public MyThread(string name) {

count = 0;

thrd = new Thread(this.run); // use method group conversion

thrd.Name = name; // set the name of the thread

thrd.Start(); // start the thread

}

// Entry point of thread.

void run() {

Console.WriteLine(thrd.Name + " starting.");

do {

Thread.Sleep(500);

Console.WriteLine("In " + thrd.Name +

", count is " + count);

count++;

} while(count < 10);

Console.WriteLine(thrd.Name + " terminating.");

}

}

class MultiThreadImproved {

public static void Main() {

Console.WriteLine("Main thread starting.");

// First, construct a MyThread object.

MyThread mt = new MyThread("Child #1");

do {

Console.Write(".");

Thread.Sleep(100);

} while (mt.count != 10);

Console.WriteLine("Main thread ending.");

}

}

listing 3

// Create multiple threads of execution.

using System;

using System.Threading;

class MyThread {

public int count;

public Thread thrd;

public MyThread(string name) {

count = 0;

thrd = new Thread(this.run);

thrd.Name = name;

thrd.Start();

}

// Entry point of thread.

void run() {

Console.WriteLine(thrd.Name + " starting.");

do {

Thread.Sleep(500);

Console.WriteLine("In " + thrd.Name +

", count is " + count);

count++;

} while(count < 10);

Console.WriteLine(thrd.Name + " terminating.");

}

}

class MoreThreads {

public static void Main() {

Console.WriteLine("Main thread starting.");

// Construct three threads.

MyThread mt1 = new MyThread("Child #1");

MyThread mt2 = new MyThread("Child #2");

MyThread mt3 = new MyThread("Child #3");

do {

Console.Write(".");

Thread.Sleep(100);

} while (mt1.count < 10 ||

mt2.count < 10 ||

mt3.count < 10);

Console.WriteLine("Main thread ending.");

}

}

listing 4

// Use IsAlive to wait for threads to end.

class MoreThreads {

public static void Main() {

Console.WriteLine("Main thread starting.");

// Construct three threads.

MyThread mt1 = new MyThread("Child #1");

MyThread mt2 = new MyThread("Child #2");

MyThread mt3 = new MyThread("Child #3");

do {

Console.Write(".");

Thread.Sleep(100);

} while (mt1.thrd.IsAlive &&

mt2.thrd.IsAlive &&

mt3.thrd.IsAlive);

Console.WriteLine("Main thread ending.");

}

}

listing 5

// Use Join().

using System;

using System.Threading;

class MyThread {

public int count;

public Thread thrd;

public MyThread(string name) {

count = 0;

thrd = new Thread(this.run);

thrd.Name = name;

thrd.Start();

}

// Entry point of thread.

void run() {

Console.WriteLine(thrd.Name + " starting.");

do {

Thread.Sleep(500);

Console.WriteLine("In " + thrd.Name +

", count is " + count);

count++;

} while(count < 10);

Console.WriteLine(thrd.Name + " terminating.");

}

}

// Use Join() to wait for threads to end.

class JoinThreads {

public static void Main() {

Console.WriteLine("Main thread starting.");

// Construct three threads.

MyThread mt1 = new MyThread("Child #1");

MyThread mt2 = new MyThread("Child #2");

MyThread mt3 = new MyThread("Child #3");

mt1.thrd.Join();

Console.WriteLine("Child #1 joined.");

mt2.thrd.Join();

Console.WriteLine("Child #2 joined.");

mt3.thrd.Join();

Console.WriteLine("Child #3 joined.");

Console.WriteLine("Main thread ending.");

}

}

listing 6

// Passing an argument to the thread method.

using System;

using System.Threading;

class MyThread {

public int count;

public Thread thrd;

// Notice that MyThread is also pass an int value.

public MyThread(string name, int num) {

count = 0;

// Explicitly invoke ParameterizedThreadStart constructor

// for the sake of illustration.

thrd = new Thread(new ParameterizedThreadStart(this.run));

thrd.Name = name;

// Here, Start() is passed num as an argument.

thrd.Start(num);

}

// Notice that this version of run() has

// a parameter of type object.

void run(object num) {

Console.WriteLine(thrd.Name +

" starting with count of " + num);

do {

Thread.Sleep(500);

Console.WriteLine("In " + thrd.Name +

", count is " + count);

count++;

} while(count < (int) num);

Console.WriteLine(thrd.Name + " terminating.");

}

}

class PassArgDemo {

public static void Main() {

// Notice that the iteration count is passed

// to these two MyThread objects.

MyThread mt = new MyThread("Child #1", 5);

MyThread mt2 = new MyThread("Child #1", 3);

do {

Thread.Sleep(100);

} while (mt.thrd.IsAlive | mt2.thrd.IsAlive);

Console.WriteLine("Main thread ending.");

}

}

listing 7

// Demonstrate thread priorities.

using System;

using System.Threading;

class MyThread {

public int count;

public Thread thrd;

static bool stop = false;

static string currentName;

/* Construct a new thread. Notice that this

constructor does not actually start the

threads running. */

public MyThread(string name) {

count = 0;

thrd = new Thread(this.run);

thrd.Name = name;

currentName = name;

}

// Begin execution of new thread.

void run() {

Console.WriteLine(thrd.Name + " starting.");

do {

count++;

if(currentName != thrd.Name) {

currentName = thrd.Name;

Console.WriteLine("In " + currentName);

}

} while(stop == false && count < 1000000000);

stop = true;

Console.WriteLine(thrd.Name + " terminating.");

}

}

class PriorityDemo {

public static void Main() {

MyThread mt1 = new MyThread("High Priority");

MyThread mt2 = new MyThread("Low Priority");

// Set the priorities.

mt1.thrd.Priority = ThreadPriority.AboveNormal;

mt2.thrd.Priority = ThreadPriority.BelowNormal;

// Start the threads.

mt1.thrd.Start();

mt2.thrd.Start();

mt1.thrd.Join();

mt2.thrd.Join();

Console.WriteLine();

Console.WriteLine(mt1.thrd.Name + " thread counted to " +

mt1.count);

Console.WriteLine(mt2.thrd.Name + " thread counted to " +

mt2.count);

}

}

listing 8

// Use lock to synchronize access to an object.

using System;

using System.Threading;

class SumArray {

int sum;

public int sumIt(int[] nums) {

lock(this) { // lock the entire method

sum = 0; // reset sum

for(int i=0; i < nums.Length; i++) {

sum += nums[i];

Console.WriteLine("Running total for " +

Thread.CurrentThread.Name +

" is " + sum);

Thread.Sleep(10); // allow task-switch

}

return sum;

}

}

}

class MyThread {

public Thread thrd;

int[] a;

int answer;

/* Create one SumArray object for all

instances of MyThread. */

static SumArray sa = new SumArray();

// Construct a new thread.

public MyThread(string name, int[] nums) {

a = nums;

thrd = new Thread(this.run);

thrd.Name = name;

thrd.Start(); // start the thread

}

// Begin execution of new thread.

void run() {

Console.WriteLine(thrd.Name + " starting.");

answer = sa.sumIt(a);

Console.WriteLine("Sum for " + thrd.Name +

" is " + answer);

Console.WriteLine(thrd.Name + " terminating.");

}

}

class Sync {

public static void Main() {

int[] a = {1, 2, 3, 4, 5};

MyThread mt1 = new MyThread("Child #1", a);

MyThread mt2 = new MyThread("Child #2", a);

mt1.thrd.Join();

mt2.thrd.Join();

}

}

listing 9

// Another way to use lock to synchronize access to an object.

using System;

using System.Threading;

class SumArray {

int sum;

public int sumIt(int[] nums) {

sum = 0; // reset sum

for(int i=0; i < nums.Length; i++) {

sum += nums[i];

Console.WriteLine("Running total for " +

Thread.CurrentThread.Name +

" is " + sum);

Thread.Sleep(10); // allow task-switch

}

return sum;

}

}

class MyThread {

public Thread thrd;

int[] a;

int answer;

/* Create one SumArray object for all

instances of MyThread. */

static SumArray sa = new SumArray();

// Construct a new thread.

public MyThread(string name, int[] nums) {

a = nums;

thrd = new Thread(this.run);

thrd.Name = name;

thrd.Start(); // start the thread

}

// Begin execution of new thread.

void run() {

Console.WriteLine(thrd.Name + " starting.");

// Lock calls to sumIt().

lock(sa) answer = sa.sumIt(a);

Console.WriteLine("Sum for " + thrd.Name +

" is " + answer);

Console.WriteLine(thrd.Name + " terminating.");

}

}

class Sync {

public static void Main() {

int[] a = {1, 2, 3, 4, 5};

MyThread mt1 = new MyThread("Child #1", a);

MyThread mt2 = new MyThread("Child #2", a);

mt1.thrd.Join();

mt2.thrd.Join();

}

}

listing 10

// Use Wait() and Pulse() to create a ticking clock.

using System;

using System.Threading;

class TickTock {

public void tick(bool running) {

lock(this) {

if(!running) { // stop the clock

Monitor.Pulse(this); // notify any waiting threads

return;

}

Console.Write("Tick ");

Monitor.Pulse(this); // let tock() run

Monitor.Wait(this); // wait for tock() to complete

}

}

public void tock(bool running) {

lock(this) {

if(!running) { // stop the clock

Monitor.Pulse(this); // notify any waiting threads

return;

}

Console.WriteLine("Tock");

Monitor.Pulse(this); // let tick() run

Monitor.Wait(this); // wait for tick() to complete

}

}

}

class MyThread {

public Thread thrd;

TickTock ttOb;

// Construct a new thread.

public MyThread(string name, TickTock tt) {

thrd = new Thread(this.run);

ttOb = tt;

thrd.Name = name;

thrd.Start();

}

// Begin execution of new thread.

void run() {

if(thrd.Name == "Tick") {

for(int i=0; i<5; i++) ttOb.tick(true);

ttOb.tick(false);

}

else {

for(int i=0; i<5; i++) ttOb.tock(true);

ttOb.tock(false);

}

}

}

class TickingClock {

public static void Main() {

TickTock tt = new TickTock();

MyThread mt1 = new MyThread("Tick", tt);

MyThread mt2 = new MyThread("Tock", tt);

mt1.thrd.Join();

mt2.thrd.Join();

Console.WriteLine("Clock Stopped");

}

}

listing 11

// A non-functional version of TickTock.

class TickTock {

public void tick(bool running) {

lock(this) {

if(!running) { // stop the clock

return;

}

Console.Write("Tick ");

}

}

public void tock(bool running) {

lock(this) {

if(!running) { // stop the clock

return;

}

Console.WriteLine("Tock");

}

}

}

listing 12

// Use MethodImplAttribute to synchronize a method.

using System;

using System.Threading;

using System.Runtime.CompilerServices;

// Rewrite of TickTock to use MethodImplOptions.Synchronized.

class TickTock {

/* The following attribute synchronizes the entire

tick() method. */

[MethodImplAttribute(MethodImplOptions.Synchronized)]

public void tick(bool running) {

if(!running) { // stop the clock

Monitor.Pulse(this); // notify any waiting threads

return;

}

Console.Write("Tick ");

Monitor.Pulse(this); // let tock() run

Monitor.Wait(this); // wait for tock() to complete

}

/* The following attribute synchronizes the entire

tock() method. */

[MethodImplAttribute(MethodImplOptions.Synchronized)]

public void tock(bool running) {

if(!running) { // stop the clock

Monitor.Pulse(this); // notify any waiting threads

return;

}

Console.WriteLine("Tock");

Monitor.Pulse(this); // let tick() run

Monitor.Wait(this); // wait for tick() to complete

}

}

class MyThread {

public Thread thrd;

TickTock ttOb;

// Construct a new thread.

public MyThread(string name, TickTock tt) {

thrd = new Thread(this.run);

ttOb = tt;

thrd.Name = name;

thrd.Start();

}

// Begin execution of new thread.

void run() {

if(thrd.Name == "Tick") {

for(int i=0; i<5; i++) ttOb.tick(true);

ttOb.tick(false);

}

else {

for(int i=0; i<5; i++) ttOb.tock(true);

ttOb.tock(false);

}

}

}

class TickingClock {

public static void Main() {

TickTock tt = new TickTock();

MyThread mt1 = new MyThread("Tick", tt);

MyThread mt2 = new MyThread("Tock", tt);

mt1.thrd.Join();

mt2.thrd.Join();

Console.WriteLine("Clock Stopped");

}

}

listing 13

// Use a Mutex.

using System;

using System.Threading;

// This class contains a shared resource (count),

// and a mutex (mtx) to control access to it.

class SharedRes {

public static int count = 0;

public static Mutex mtx = new Mutex();

}

// This thread increments SharedRes.count.

class IncThread {

int num;

public Thread thrd;

public IncThread(string name, int n) {

thrd = new Thread(this.run);

num = n;

thrd.Name = name;

thrd.Start();

}

// Entry point of thread.

void run() {

Console.WriteLine(thrd.Name + " is waiting for the mutex.");

// Acquire the Mutex.

SharedRes.mtx.WaitOne();

Console.WriteLine(thrd.Name + " acquires the mutex.");

do {

Thread.Sleep(500);

SharedRes.count++;

Console.WriteLine("In " + thrd.Name +

", SharedRes.count is " + SharedRes.count);

num--;

} while(num > 0);

Console.WriteLine(thrd.Name + " releases the mutex.");

// Release the Mutex.

SharedRes.mtx.ReleaseMutex();

}

}

// This thread decrements SharedRes.count.

class DecThread {

int num;

public Thread thrd;

public DecThread(string name, int n) {

thrd = new Thread(new ThreadStart(this.run));

num = n;

thrd.Name = name;

thrd.Start();

}

// Entry point of thread.

void run() {

Console.WriteLine(thrd.Name + " is waiting for the mutex.");

// Acquire the Mutex.

SharedRes.mtx.WaitOne();

Console.WriteLine(thrd.Name + " acquires the mutex.");

do {

Thread.Sleep(500);

SharedRes.count--;

Console.WriteLine("In " + thrd.Name +

", SharedRes.count is " + SharedRes.count);

num--;

} while(num > 0);

Console.WriteLine(thrd.Name + " releases the mutex.");

// Release the Mutex.

SharedRes.mtx.ReleaseMutex();

}

}

class MutexDemo {

public static void Main() {

// Construct three threads.

IncThread mt1 = new IncThread("Increment Thread", 5);

DecThread mt2 = new DecThread("Decrement Thread", 5);

mt1.thrd.Join();

mt2.thrd.Join();

}

}

listing 14

// Use a Semaphore

using System;

using System.Threading;

// This thread allows only two instances of itself

// to run at any one time.

class MyThread {

public Thread thrd;

// This creates a semaphore that allows up to 2

// permits to be granted and that initially has

// two permits available.

static Semaphore sem = new Semaphore(2, 2);

public MyThread(string name) {

thrd = new Thread(this.run);

thrd.Name = name;

thrd.Start();

}

// Entry point of thread.

void run() {

Console.WriteLine(thrd.Name + " is waiting for a permit.");

sem.WaitOne();

Console.WriteLine(thrd.Name + " acquires a permit.");

for(char ch='A'; ch < 'D'; ch++) {

Console.WriteLine(thrd.Name + " : " + ch + " ");

Thread.Sleep(500);

}

Console.WriteLine(thrd.Name + " releases a permit.");

// Release the semaphore.

sem.Release();

}

}

class SemaphoreDemo {

public static void Main() {

// Construct three threads.

MyThread mt1 = new MyThread("Thread #1");

MyThread mt2 = new MyThread("Thread #2");

MyThread mt3 = new MyThread("Thread #3");

mt1.thrd.Join();

mt2.thrd.Join();

mt3.thrd.Join();

}

}

listing 15

// Use a manual event object.

using System;

using System.Threading;

// This thread signals the event passed to its constructor.

class MyThread {

public Thread thrd;

ManualResetEvent mre;

public MyThread(string name, ManualResetEvent evt) {

thrd = new Thread(this.run);

thrd.Name = name;

mre = evt;

thrd.Start();

}

// Entry point of thread.

void run() {

Console.WriteLine("Inside thread " + thrd.Name);

for(int i=0; i<5; i++) {

Console.WriteLine(thrd.Name);

Thread.Sleep(500);

}

Console.WriteLine(thrd.Name + " Done!");

// Signal the event.

mre.Set();

}

}

class ManualEventDemo {

public static void Main() {

ManualResetEvent evtObj = new ManualResetEvent(false);

MyThread mt1 = new MyThread("Event Thread 1", evtObj);

Console.WriteLine("Main thread waiting for event.");

// Wait for signaled event.

evtObj.WaitOne();

Console.WriteLine("Main thread received first event.");

// Reset the event.

evtObj.Reset();

mt1 = new MyThread("Event Thread 2", evtObj);

// Wait for signaled event.

evtObj.WaitOne();

Console.WriteLine("Main thread received second event.");

}

}

listing 16

// Use Interlocked operations.

using System;

using System.Threading;

// A shared resource.

class SharedRes {

public static int count = 0;

}

// This thread increments SharedRes.count.

class IncThread {

public Thread thrd;

public IncThread(string name) {

thrd = new Thread(this.run);

thrd.Name = name;

thrd.Start();

}

// Entry point of thread.

void run() {

for(int i=0; i<5; i++) {

Interlocked.Increment(ref SharedRes.count);

Console.WriteLine(thrd.Name + " count is " + SharedRes.count);

}

}

}

// This thread decrements SharedRes.count.

class DecThread {

public Thread thrd;

public DecThread(string name) {

thrd = new Thread(this.run);

thrd.Name = name;

thrd.Start();

}

// Entry point of thread.

void run() {

for(int i=0; i<5; i++) {

Interlocked.Decrement(ref SharedRes.count);

Console.WriteLine(thrd.Name + " count is " + SharedRes.count);

}

}

}

class InterdlockedDemo {

public static void Main() {

// Construct two threads.

IncThread mt1 = new IncThread("Increment Thread");

DecThread mt2 = new DecThread("Decrement Thread");

mt1.thrd.Join();

mt2.thrd.Join();

}

}

listing 17

// Stopping a thread.

using System;

using System.Threading;

class MyThread {

public Thread thrd;

public MyThread(string name) {

thrd = new Thread(this.run);

thrd.Name = name;

thrd.Start();

}

// This is the entry point for thread.

void run() {

Console.WriteLine(thrd.Name + " starting.");

for(int i = 1; i <= 1000; i++) {

Console.Write(i + " ");

if((i%10)==0) {

Console.WriteLine();

Thread.Sleep(250);

}

}

Console.WriteLine(thrd.Name + " exiting.");

}

}

class StopDemo {

public static void Main() {

MyThread mt1 = new MyThread("My Thread");

Thread.Sleep(1000); // let child thread start executing

Console.WriteLine("Stopping thread.");

mt1.thrd.Abort();

mt1.thrd.Join(); // wait for thread to terminate

Console.WriteLine("Main thread terminating.");

}

}

listing 18

// Using Abort(object).

using System;

using System.Threading;

class MyThread {

public Thread thrd;

public MyThread(string name) {

thrd = new Thread(this.run);

thrd.Name = name;

thrd.Start();

}

// This is the entry point for thread.

void run() {

try {

Console.WriteLine(thrd.Name + " starting.");

for(int i = 1; i <= 1000; i++) {

Console.Write(i + " ");

if((i%10)==0) {

Console.WriteLine();

Thread.Sleep(250);

}

}

Console.WriteLine(thrd.Name + " exiting normally.");

} catch(ThreadAbortException exc) {

Console.WriteLine("Thread aborting, code is " +

exc.ExceptionState);

}

}

}

class UseAltAbort {

public static void Main() {

MyThread mt1 = new MyThread("My Thread");

Thread.Sleep(1000); // let child thread start executing

Console.WriteLine("Stopping thread.");

mt1.thrd.Abort(100);

mt1.thrd.Join(); // wait for thread to terminate

Console.WriteLine("Main thread terminating.");

}

}

listing 19

// Using ResetAbort().

using System;

using System.Threading;

class MyThread {

public Thread thrd;

public MyThread(string name) {

thrd = new Thread(this.run);

thrd.Name = name;

thrd.Start();

}

// This is the entry point for thread.

void run() {

Console.WriteLine(thrd.Name + " starting.");

for(int i = 1; i <= 1000; i++) {

try {

Console.Write(i + " ");

if((i%10)==0) {

Console.WriteLine();

Thread.Sleep(250);

}

} catch(ThreadAbortException exc) {

if((int)exc.ExceptionState == 0) {

Console.WriteLine("Abort Cancelled! Code is " +

exc.ExceptionState);

Thread.ResetAbort();

}

else

Console.WriteLine("Thread aborting, code is " +

exc.ExceptionState);

}

}

Console.WriteLine(thrd.Name + " exiting normally.");

}

}

class ResetAbort {

public static void Main() {

MyThread mt1 = new MyThread("My Thread");

Thread.Sleep(1000); // let child thread start executing

Console.WriteLine("Stopping thread.");

mt1.thrd.Abort(0); // this won't stop the thread

Thread.Sleep(1000); // let child execute a bit longer

Console.WriteLine("Stopping thread.");

mt1.thrd.Abort(100); // this will stop the thread

mt1.thrd.Join(); // wait for thread to terminate

Console.WriteLine("Main thread terminating.");

}

}

listing 20

// Control the main thread.

using System;

using System.Threading;

class UseMain {

public static void Main() {

Thread thrd;

// Get the main thread.

thrd = Thread.CurrentThread;

// Display main thread's name.

if(thrd.Name == null)

Console.WriteLine("Main thread has no name.");

else

Console.WriteLine("Main thread is called: " + thrd.Name);

// Display main thread's priority.

Console.WriteLine("Priority: " + thrd.Priority);

Console.WriteLine();

// Set the name and priority.

Console.WriteLine("Setting name and priority.\n");

thrd.Name = "Main Thread";

thrd.Priority = ThreadPriority.AboveNormal;

Console.WriteLine("Main thread is now called: " +

thrd.Name);

Console.WriteLine("Priority is now: " +

thrd.Priority);

}

}

listing 21

// Starting a new process.

using System;

using System.Diagnostics;

class StartProcess {

public static void Main() {

Process newProc = Process.Start("wordpad.exe");

Console.WriteLine("New process started.");

newProc.WaitForExit();

newProc.Close(); // free resources

Console.WriteLine("New process ended.");

}

}

listing 1

// Demonstrate ArrayList.

using System;

using System.Collections;

class ArrayListDemo {

public static void Main() {

// create an array list

ArrayList al = new ArrayList();

Console.WriteLine("Initial number of elements: " +

al.Count);

Console.WriteLine();

Console.WriteLine("Adding 6 elements");

// Add elements to the array list

al.Add('C');

al.Add('A');

al.Add('E');

al.Add('B');

al.Add('D');

al.Add('F');

Console.WriteLine("Number of elements: " +

al.Count);

// Display the array list using array indexing.

Console.Write("Current contents: ");

for(int i=0; i < al.Count; i++)

Console.Write(al[i] + " ");

Console.WriteLine("\n");

Console.WriteLine("Removing 2 elements");

// Remove elements from the array list.

al.Remove('F');

al.Remove('A');

Console.WriteLine("Number of elements: " +

al.Count);

// Use foreach loop to display the list.

Console.Write("Contents: ");

foreach(char c in al)

Console.Write(c + " ");

Console.WriteLine("\n");

Console.WriteLine("Adding 20 more elements");

// Add enough elements to force al to grow.

for(int i=0; i < 20; i++)

al.Add((char)('a' + i));

Console.WriteLine("Current capacity: " +

al.Capacity);

Console.WriteLine("Number of elements after adding 20: " +

al.Count);

Console.Write("Contents: ");

foreach(char c in al)

Console.Write(c + " ");

Console.WriteLine("\n");

// Change contents using array indexing.

Console.WriteLine("Change first three elements");

al[0] = 'X';

al[1] = 'Y';

al[2] = 'Z';

Console.Write("Contents: ");

foreach(char c in al)

Console.Write(c + " ");

Console.WriteLine();

}

}

listing 2

// Sort and search an ArrayList.

using System;

using System.Collections;

class SortSearchDemo {

public static void Main() {

// create an array list

ArrayList al = new ArrayList();

// Add elements to the array list

al.Add(55);

al.Add(43);

al.Add(-4);

al.Add(88);

al.Add(3);

al.Add(19);

Console.Write("Original contents: ");

foreach(int i in al)

Console.Write(i + " ");

Console.WriteLine("\n");

// Sort

al.Sort();

// Use foreach loop to display the list.

Console.Write("Contents after sorting: ");

foreach(int i in al)

Console.Write(i + " ");

Console.WriteLine("\n");

Console.WriteLine("Index of 43 is " +

al.BinarySearch(43));

}

}

listing 3

// Convert an ArrayList into an array.

using System;

using System.Collections;

class ArrayListToArray {

public static void Main() {

ArrayList al = new ArrayList();

// Add elements to the array list.

al.Add(1);

al.Add(2);

al.Add(3);

al.Add(4);

Console.Write("Contents: ");

foreach(int i in al)

Console.Write(i + " ");

Console.WriteLine();

// Get the array.

int[] ia = (int[]) al.ToArray(typeof(int));

int sum = 0;

// sum the array

for(int i=0; i<ia.Length; i++)

sum += ia[i];

Console.WriteLine("Sum is: " + sum);

}

}

listing 4

// Demonstrate Hashtable.

using System;

using System.Collections;

class HashtableDemo {

public static void Main() {

// Create a hash table.

Hashtable ht = new Hashtable();

// Add elements to the table

ht.Add("house", "Dwelling");

ht.Add("car", "Means of transport");

ht.Add("book", "Collection of printed words");

ht.Add("apple", "Edible fruit");

// Can also add by using the indexer.

ht["tractor"] = "Farm implement";

// Get a collection of the keys.

ICollection c = ht.Keys;

// Use the keys to obtain the values.

foreach(string str in c)

Console.WriteLine(str + ": " + ht[str]);

}

}

listing 5

// Demonstrate a SortedList.

using System;

using System.Collections;

class SLDemo {

public static void Main() {

// Create a sorted SortedList.

SortedList sl = new SortedList();

// Add elements to the table

sl.Add("house", "Dwelling");

sl.Add("car", "Means of transport");

sl.Add("book", "Collection of printed words");

sl.Add("apple", "Edible fruit");

// Can also add by using the indexer.

sl["tractor"] = "Farm implement";

// Get a collection of the keys.

ICollection c = sl.Keys;

// Use the keys to obtain the values.

Console.WriteLine("Contents of list via indexer.");

foreach(string str in c)

Console.WriteLine(str + ": " + sl[str]);

Console.WriteLine();

// Display list using integer indexes.

Console.WriteLine("Contents by integer indexes.");

for(int i=0; i<sl.Count; i++)

Console.WriteLine(sl.GetByIndex(i));

Console.WriteLine();

// Show integer indexes of entries.

Console.WriteLine("Integer indexes of entries.");

foreach(string str in c)

Console.WriteLine(str + ": " + sl.IndexOfKey(str));

}

}

listing 6

// Demonstrate the Stack class.

using System;

using System.Collections;

class StackDemo {

static void showPush(Stack st, int a) {

st.Push(a);

Console.WriteLine("Push(" + a + ")");

Console.Write("stack: ");

foreach(int i in st)

Console.Write(i + " ");

Console.WriteLine();

}

static void showPop(Stack st) {

Console.Write("Pop -> ");

int a = (int) st.Pop();

Console.WriteLine(a);

Console.Write("stack: ");

foreach(int i in st)

Console.Write(i + " ");

Console.WriteLine();

}

public static void Main() {

Stack st = new Stack();

foreach(int i in st)

Console.Write(i + " ");

Console.WriteLine();

showPush(st, 22);

showPush(st, 65);

showPush(st, 91);

showPop(st);

showPop(st);

showPop(st);

try {

showPop(st);

} catch (InvalidOperationException) {

Console.WriteLine("Stack empty.");

}

}

}

listing 7

// Demonstrate the Queue class.

using System;

using System.Collections;

class QueueDemo {

static void showEnq(Queue q, int a) {

q.Enqueue(a);

Console.WriteLine("Enqueue(" + a + ")");

Console.Write("queue: ");

foreach(int i in q)

Console.Write(i + " ");

Console.WriteLine();

}

static void showDeq(Queue q) {

Console.Write("Dequeue -> ");

int a = (int) q.Dequeue();

Console.WriteLine(a);

Console.Write("queue: ");

foreach(int i in q)

Console.Write(i + " ");

Console.WriteLine();

}

public static void Main() {

Queue q = new Queue();

foreach(int i in q)

Console.Write(i + " ");

Console.WriteLine();

showEnq(q, 22);

showEnq(q, 65);

showEnq(q, 91);

showDeq(q);

showDeq(q);

showDeq(q);

try {

showDeq(q);

} catch (InvalidOperationException) {

Console.WriteLine("Queue empty.");

}

}

}

listing 8

// Demonstrate BitArray.

using System;

using System.Collections;

class BADemo {

public static void showbits(string rem,

BitArray bits) {

Console.WriteLine(rem);

for(int i=0; i < bits.Count; i++)

Console.Write("{0, -6} ", bits[i]);

Console.WriteLine("\n");

}

public static void Main() {

BitArray ba = new BitArray(8);

byte[] b = { 67 };

BitArray ba2 = new BitArray(b);

showbits("Original contents of ba:", ba);

ba = ba.Not();

showbits("Contents of ba after Not:", ba);

showbits("Contents of ba2:", ba2);

BitArray ba3 = ba.Xor(ba2);

showbits("Result of ba XOR ba2:", ba3);

}

}

listing 9

// Demonstrate List<T>.

using System;

using System.Collections.Generic;

class GenListDemo {

public static void Main() {

// Create a list.

List<char> lst = new List<char>();

Console.WriteLine("Initial number of elements: " +

lst.Count);

Console.WriteLine();

Console.WriteLine("Adding 6 elements");

// Add elements to the array list

lst.Add('C');

lst.Add('A');

lst.Add('E');

lst.Add('B');

lst.Add('D');

lst.Add('F');

Console.WriteLine("Number of elements: " +

lst.Count);

// Display the array list using array indexing.

Console.Write("Current contents: ");

for(int i=0; i < lst.Count; i++)

Console.Write(lst[i] + " ");

Console.WriteLine("\n");

Console.WriteLine("Removing 2 elements");

// Remove elements from the array list.

lst.Remove('F');

lst.Remove('A');

Console.WriteLine("Number of elements: " +

lst.Count);

// Use foreach loop to display the list.

Console.Write("Contents: ");

foreach(char c in lst)

Console.Write(c + " ");

Console.WriteLine("\n");

Console.WriteLine("Adding 20 more elements");

// Add enough elements to force lst to grow.

for(int i=0; i < 20; i++)

lst.Add((char)('a' + i));

Console.WriteLine("Current capacity: " +

lst.Capacity);

Console.WriteLine("Number of elements after adding 20: " +

lst.Count);

Console.Write("Contents: ");

foreach(char c in lst)

Console.Write(c + " ");

Console.WriteLine("\n");

// Change contents using array indexing.

Console.WriteLine("Change first three elements");

lst[0] = 'X';

lst[1] = 'Y';

lst[2] = 'Z';

Console.Write("Contents: ");

foreach(char c in lst)

Console.Write(c + " ");

Console.WriteLine();

// Because of generic type-safety,

// the following line is illegal.

// lst.Add(99); // Error, not a char!

}

}

listing 10

// Demonstrate LinkedList<T>.

using System;

using System.Collections.Generic;

class GenLinkedListDemo {

public static void Main() {

// Create an linked list.

LinkedList<char> ll = new LinkedList<char>();

Console.WriteLine("Initial number of elements: " +

ll.Count);

Console.WriteLine();

Console.WriteLine("Adding 5 elements.");

// Add elements to the linked list

ll.AddFirst('A');

ll.AddFirst('B');

ll.AddFirst('C');

ll.AddFirst('D');

ll.AddFirst('E');

Console.WriteLine("Number of elements: " +

ll.Count);

// Display the linked list by manually walking

// through the list.

LinkedListNode<char> node;

Console.Write("Display contents by following links: ");

for(node = ll.First; node != null; node = node.Next)

Console.Write(node.Value + " ");

Console.WriteLine("\n");

//Display the linked list by use of a foreach loop.

Console.Write("Display contents with foreach loop: ");

foreach(char ch in ll)

Console.Write(ch + " ");

Console.WriteLine("\n");

// Display the list backwards by manually walking

// from last to first.

Console.Write("Follow links backwards: ");

for(node = ll.Last; node != null; node = node.Previous)

Console.Write(node.Value + " ");

Console.WriteLine("\n");

// Remove two elements.

Console.WriteLine("Removing 2 elements.");

// Remove elements from the linked list.

ll.Remove('C');

ll.Remove('A');

Console.WriteLine("Number of elements: " +

ll.Count);

// Use foreach loop to display the modified list.

Console.Write("Contents after deletion: ");

foreach(char ch in ll)

Console.Write(ch + " ");

Console.WriteLine("\n");

// Add three elements to the end of the list.

ll.AddLast('X');

ll.AddLast('Y');

ll.AddLast('Z');

Console.Write("Contents after addition to end: ");

foreach(char ch in ll)

Console.Write(ch + " ");

Console.WriteLine("\n");

}

}

listing 11

// Demonstrate the generic Dictionary<TK, TV> class.

using System;

using System.Collections.Generic;

class GenDictionaryDemo {

public static void Main() {

// Create a Dictionary that holds employee

// names and their corresponding salaries.

Dictionary<string, double> dict =

new Dictionary<string, double>();

// Add elements to the collection.

dict.Add("Butler, John", 73000);

dict.Add("Swartz, Sarah", 59000);

dict.Add("Pyke, Thomas", 45000);

dict.Add("Frank, Ed", 99000);

// Get a collection of the keys (names).

ICollection<string> c = dict.Keys;

// Use the keys to obtain the values (salares).

foreach(string str in c)

Console.WriteLine("{0}, Salary: {1:C}", str, dict[str]);

}

}

listing 12

// Demonstrate the generic SortedDictionary<TK, TV> class.

using System;

using System.Collections.Generic;

class GenSortedDictionaryDemo {

public static void Main() {

// Create a Dictionary that holds employee

// names and their corresponding salaries.

SortedDictionary<string, double> dict =

new SortedDictionary<string, double>();

// Add elements to the collection.

dict.Add("Butler, John", 73000);

dict.Add("Swartz, Sarah", 59000);

dict.Add("Pyke, Thomas", 45000);

dict.Add("Frank, Ed", 99000);

// Get a collection of the keys (names).

ICollection<string> c = dict.Keys;

// Use the keys to obtain the values (salares).

foreach(string str in c)

Console.WriteLine("{0}, Salary: {1:C}", str, dict[str]);

}

}

listing 13

// Demonstrate a SortedList<TK, TV>.

using System;

using System.Collections.Generic;

class GenSLDemo {

public static void Main() {

// Create a sorted SortedList<T> for

// employee names and salaries.

SortedList<string, double> sl =

new SortedList<string, double>();

// Add elements to the collection.

sl.Add("Butler, John", 73000);

sl.Add("Swartz, Sarah", 59000);

sl.Add("Pyke, Thomas", 45000);

sl.Add("Frank, Ed", 99000);

// Get a collection of the keys.

ICollection<string> c = sl.Keys;

// Use the keys to obtain the values.

foreach(string str in c)

Console.WriteLine("{0}, Salary: {1:C}", str, sl[str]);

Console.WriteLine();

}

}

listing 14

// Demonstrate the Stack<T> class.

using System;

using System.Collections.Generic;

class GenStackDemo {

public static void Main() {

Stack<string> st = new Stack<string>();

st.Push("One");

st.Push("Two");

st.Push("Three");

st.Push("Four");

st.Push("Five");

while(st.Count > 0) {

string str = st.Pop();

Console.Write(str + " ");

}

Console.WriteLine();

}

}

listing 15

// Demonstrate the Queue<T> class.

using System;

using System.Collections.Generic;

class GenQueueDemo {

public static void Main() {

Queue<double> q = new Queue<double>();

q.Enqueue(98.6);

q.Enqueue(212.0);

q.Enqueue(32.0);

q.Enqueue(3.1416);

double sum = 0.0;

Console.Write("Queue contents: ");

while(q.Count > 0) {

double val = q.Dequeue();

Console.Write(val + " ");

sum += val;

}

Console.WriteLine("\nTotal is " + sum);

}

}

listing 16

// A simple inventory example.

using System;

using System.Collections;

class Inventory {

string name;

double cost;

int onhand;

public Inventory(string n, double c, int h) {

name = n;

cost = c;

onhand = h;

}

public override string ToString() {

return

String.Format("{0,-10}Cost: {1,6:C} On hand: {2}",

name, cost, onhand);

}

}

class InventoryList {

public static void Main() {

ArrayList inv = new ArrayList();

// Add elements to the list

inv.Add(new Inventory("Pliers", 5.95, 3));

inv.Add(new Inventory("Wrenches", 8.29, 2));

inv.Add(new Inventory("Hammers", 3.50, 4));

inv.Add(new Inventory("Drills", 19.88, 8));

Console.WriteLine("Inventory list:");

foreach(Inventory i in inv) {

Console.WriteLine(" " + i);

}

}

}

listing 17

// Store Inventory Objects in a List<T> collection.

using System;

using System.Collections.Generic;

class Inventory {

string name;

double cost;

int onhand;

public Inventory(string n, double c, int h) {

name = n;

cost = c;

onhand = h;

}

public override string ToString() {

return

String.Format("{0,-10}Cost: {1,6:C} On hand: {2}",

name, cost, onhand);

}

}

class TypeSafeInventoryList {

public static void Main() {

List<Inventory> inv = new List<Inventory>();

// Add elements to the list

inv.Add(new Inventory("Pliers", 5.95, 3));

inv.Add(new Inventory("Wrenches", 8.29, 2));

inv.Add(new Inventory("Hammers", 3.50, 4));

inv.Add(new Inventory("Drills", 19.88, 8));

Console.WriteLine("Inventory list:");

foreach(Inventory i in inv) {

Console.WriteLine(" " + i);

}

}

}

listing 18

// Implement IComparable.

using System;

using System.Collections;

// Implement the non-generic IComparable interface.

class Inventory : IComparable {

string name;

double cost;

int onhand;

public Inventory(string n, double c, int h) {

name = n;

cost = c;

onhand = h;

}

public override string ToString() {

return

String.Format("{0,-10}Cost: {1,6:C} On hand: {2}",

name, cost, onhand);

}

// Implement the IComparable interface.

public int CompareTo(object obj) {

Inventory b;

b = (Inventory) obj;

return name.CompareTo(b.name);

}

}

class IComparableDemo {

public static void Main() {

ArrayList inv = new ArrayList();

// Add elements to the list

inv.Add(new Inventory("Pliers", 5.95, 3));

inv.Add(new Inventory("Wrenches", 8.29, 2));

inv.Add(new Inventory("Hammers", 3.50, 4));

inv.Add(new Inventory("Drills", 19.88, 8));

Console.WriteLine("Inventory list before sorting:");

foreach(Inventory i in inv) {

Console.WriteLine(" " + i);

}

Console.WriteLine();

// Sort the list.

inv.Sort();

Console.WriteLine("Inventory list after sorting:");

foreach(Inventory i in inv) {

Console.WriteLine(" " + i);

}

}

}

listing 19

// Implement IComparable<T>.

using System;

using System.Collections.Generic;

// Implement the generic IComparable<T> interface.

class Inventory : IComparable<Inventory> {

string name;

double cost;

int onhand;

public Inventory(string n, double c, int h) {

name = n;

cost = c;

onhand = h;

}

public override string ToString() {

return

String.Format("{0,-10}Cost: {1,6:C} On hand: {2}",

name, cost, onhand);

}

// Implement the IComparable<T> interface.

public int CompareTo(Inventory obj) {

return name.CompareTo(obj.name);

}

}

class GenericIComparableDemo {

public static void Main() {

List<Inventory> inv = new List<Inventory>();

// Add elements to the list

inv.Add(new Inventory("Pliers", 5.95, 3));

inv.Add(new Inventory("Wrenches", 8.29, 2));

inv.Add(new Inventory("Hammers", 3.50, 4));

inv.Add(new Inventory("Drills", 19.88, 8));

Console.WriteLine("Inventory list before sorting:");

foreach(Inventory i in inv) {

Console.WriteLine(" " + i);

}

Console.WriteLine();

// Sort the list.

inv.Sort();

Console.WriteLine("Inventory list after sorting:");

foreach(Inventory i in inv) {

Console.WriteLine(" " + i);

}

}

}

listing 20

// Use IComparer.

using System;

using System.Collections;

// Create an IComparer for Inventory objects.

class CompInv : IComparer {

// Implement the IComparable interface.

public int Compare(object obj1, object obj2) {

Inventory a, b;

a = (Inventory) obj1;

b = (Inventory) obj2;

return a.name.CompareTo(b.name);

}

}

class Inventory {

public string name;

double cost;

int onhand;

public Inventory(string n, double c, int h) {

name = n;

cost = c;

onhand = h;

}

public override string ToString() {

return

String.Format("{0,-10}Cost: {1,6:C} On hand: {2}",

name, cost, onhand);

}

}

class IComparerDemo {

public static void Main() {

CompInv comp = new CompInv();

ArrayList inv = new ArrayList();

// Add elements to the list

inv.Add(new Inventory("Pliers", 5.95, 3));

inv.Add(new Inventory("Wrenches", 8.29, 2));

inv.Add(new Inventory("Hammers", 3.50, 4));

inv.Add(new Inventory("Drills", 19.88, 8));

Console.WriteLine("Inventory list before sorting:");

foreach(Inventory i in inv) {

Console.WriteLine(" " + i);

}

Console.WriteLine();

// Sort the list using an IComparer.

inv.Sort(comp);

Console.WriteLine("Inventory list after sorting:");

foreach(Inventory i in inv) {

Console.WriteLine(" " + i);

}

}

}

listing 21

// Use IComparer<T>.

using System;

using System.Collections.Generic;

// Create an IComparer<T> for Inventory objects.

class CompInv<T> : IComparer<T> where T : Inventory {

// Implement the IComparer<T> interface.

public int Compare(T obj1, T obj2) {

return obj1.name.CompareTo(obj2.name);

}

}

class Inventory {

public string name;

double cost;

int onhand;

public Inventory(string n, double c, int h) {

name = n;

cost = c;

onhand = h;

}

public override string ToString() {

return

String.Format("{0,-10}Cost: {1,6:C} On hand: {2}",

name, cost, onhand);

}

}

class GenericIComparerDemo {

public static void Main() {

CompInv<Inventory> comp = new CompInv<Inventory>();

List<Inventory> inv = new List<Inventory>();

// Add elements to the list

inv.Add(new Inventory("Pliers", 5.95, 3));

inv.Add(new Inventory("Wrenches", 8.29, 2));

inv.Add(new Inventory("Hammers", 3.50, 4));

inv.Add(new Inventory("Drills", 19.88, 8));

Console.WriteLine("Inventory list before sorting:");

foreach(Inventory i in inv) {

Console.WriteLine(" " + i);

}

Console.WriteLine();

// Sort the list using an IComparer.

inv.Sort(comp);

Console.WriteLine("Inventory list after sorting:");

foreach(Inventory i in inv) {

Console.WriteLine(" " + i);

}

}

}

listing 22

// Demonstrate an enumerator.

using System;

using System.Collections;

class EnumeratorDemo {

public static void Main() {

ArrayList list = new ArrayList(1);

for(int i=0; i < 10; i++)

list.Add(i);

// Use enumerator to access list.

IEnumerator etr = list.GetEnumerator();

while(etr.MoveNext())

Console.Write(etr.Current + " ");

Console.WriteLine();

// Re杄numerate the list.

etr.Reset();

while(etr.MoveNext())

Console.Write(etr.Current + " ");

Console.WriteLine();

}

}

listing 23

// Demonstrate IDictionaryEnumerator.

using System;

using System.Collections;

class IDicEnumDemo {

public static void Main() {

// Create a hash table.

Hashtable ht = new Hashtable();

// Add elements to the table

ht.Add("Tom", "555?456");

ht.Add("Mary", "555?876");

ht.Add("Todd", "555?452");

ht.Add("Ken", "555?756");

// Demonstrate enumerator

IDictionaryEnumerator etr = ht.GetEnumerator();

Console.WriteLine("Display info using Entry.");

while(etr.MoveNext())

Console.WriteLine(etr.Entry.Key + ": " +

etr.Entry.Value);

Console.WriteLine();

Console.WriteLine("Display info using Key and Value directly.");

etr.Reset();

while(etr.MoveNext())

Console.WriteLine(etr.Key + ": " +

etr.Value);

}

}

listing 24

// Implement IEnumerable and IEnumerator.

using System;

using System.Collections;

class MyClass : IEnumerator, IEnumerable {

char[] chrs = { 'A', 'B', 'C', 'D' };

int idx = -1;

// Implement IEnumerable.

public IEnumerator GetEnumerator() {

return this;

}

// The following methods implement IEnumerator.

// Return the current object.

public object Current {

get {

return chrs[idx];

}

}

// Advance to the next object.

public bool MoveNext() {

if(idx == chrs.Length-1) {

Reset(); // reset enumerator at the end.

return false;

}

idx++;

return true;

}

// Reset the enumerator to the start.

public void Reset() { idx = -1; }

}

class EnumeratorImplDemo {

public static void Main() {

MyClass mc = new MyClass();

// Display the contents of mc.

foreach(char ch in mc)

Console.Write(ch + " ");

Console.WriteLine();

// Display the contents of mc, again.

foreach(char ch in mc)

Console.Write(ch + " ");

Console.WriteLine();

}

}

listing 25

// A simple example of an iterator.

using System;

using System.Collections;

class MyClass {

char[] chrs = { 'A', 'B', 'C', 'D' };

// This iterator returns the characters

// in the chrs array.

public IEnumerator GetEnumerator() {

foreach(char ch in chrs)

yield return ch;

}

}

class ItrDemo {

public static void Main() {

MyClass mc = new MyClass();

foreach(char ch in mc)

Console.Write(ch + " ");

Console.WriteLine();

}

}

listing 26

// Iterated values can be dynamically constructed.

using System;

using System.Collections;

class MyClass {

char ch = 'A';

// This iterator returns the letters

// of the alphabet.

public IEnumerator GetEnumerator() {

for(int i=0; i < 26; i++)

yield return (char) (ch + i);

}

}

class ItrDemo2 {

public static void Main() {

MyClass mc = new MyClass();

foreach(char ch in mc)

Console.Write(ch + " ");

Console.WriteLine();

}

}

listing 27

// Use yield break.

using System;

using System.Collections;

class MyClass {

char ch = 'A';

// This iterator returns the first 10

// letters of the alphabet.

public IEnumerator GetEnumerator() {

for(int i=0; i < 26; i++) {

if(i == 10) yield break; // stop iterator early

yield return (char) (ch + i);

}

}

}

class ItrDemo3 {

public static void Main() {

MyClass mc = new MyClass();

foreach(char ch in mc)

Console.Write(ch + " ");

Console.WriteLine();

}

}

listing 28

// Multiple yield statements are allowed.

using System;

using System.Collections;

class MyClass {

// This iterator returns the letters

// A, B, C, D and E.

public IEnumerator GetEnumerator() {

yield return 'A';

yield return 'B';

yield return 'C';

yield return 'D';

yield return 'E';

}

}

class ItrDemo5 {

public static void Main() {

MyClass mc = new MyClass();

foreach(char ch in mc)

Console.Write(ch + " ");

Console.WriteLine();

}

}

listing 29

// Use named iterators and the Enumerable pattern.

using System;

using System.Collections;

class MyClass {

char ch = 'A';

// This iterator returns the letters

// of the alphabet, beginning at A and

// stopping at the specified starting point.

public IEnumerable MyItr(int end) {

for(int i=0; i < end; i++)

yield return (char) (ch + i);

}

// This iterator returns the specified

// range of letters

public IEnumerable MyItr(int begin, int end) {

for(int i=begin; i < end; i++)

yield return (char) (ch + i);

}

}

class ItrDemo4 {

public static void Main() {

MyClass mc = new MyClass();

Console.WriteLine("Iterator the first 7 letters:");

foreach(char ch in mc.MyItr(7))

Console.Write(ch + " ");

Console.WriteLine("\n");

Console.WriteLine("Iterate letters from F to L:");

foreach(char ch in mc.MyItr(5, 12))

Console.Write(ch + " ");

Console.WriteLine();

}

}

listing 30

// A simple example of a generic iterator.

using System;

using System.Collections.Generic;

class MyClass<T> {

T[] array;

public MyClass(T[] a) {

array = a;

}

// This iterator returns the characters

// in the chrs array.

public IEnumerator<T> GetEnumerator() {

foreach(T obj in array)

yield return obj;

}

}

class GenericItrDemo {

public static void Main() {

int[] nums = { 4, 3, 6, 4, 7, 9 };

MyClass<int> mc = new MyClass<int>(nums);

foreach(int x in mc)

Console.Write(x + " ");

Console.WriteLine();

bool[] bVals = { true, true, false, true };

MyClass<bool> mc2 = new MyClass<bool>(bVals);

foreach(bool b in mc2)

Console.Write(b + " ");

Console.WriteLine();

}

}

listing 1

// Access the Internet.

using System;

using System.Net;

using System.IO;

class NetDemo {

public static void Main() {

int ch;

// First, create a WebRequest to a URI.

HttpWebRequest req = (HttpWebRequest)

WebRequest.Create("http://www.McGraw-Hill.com");

// Next, send that request and return the response.

HttpWebResponse resp = (HttpWebResponse)

req.GetResponse();

// From the response, obtain an input stream.

Stream istrm = resp.GetResponseStream();

/* Now, read and display the html present at

the specified URI. So you can see what is

being displayed, the data is shown

400 characters at a time. After each 400

characters are displayed, you must press

ENTER to get the next 400. */

for(int i=1; ; i++) {

ch = istrm.ReadByte();

if(ch == -1) break;

Console.Write((char) ch);

if((i%400)==0) {

Console.Write("\nPress Enter.");

Console.ReadLine();

}

}

// Close the Response. This also closes istrm.

resp.Close();

}

}

listing 2

// Handle network exceptions.

using System;

using System.Net;

using System.IO;

class NetExcDemo {

public static void Main() {

int ch;

try {

// First, create a WebRequest to a URI.

HttpWebRequest req = (HttpWebRequest)

WebRequest.Create("http://www.McGraw-Hill.com");

// Next, send that request and return the response.

HttpWebResponse resp = (HttpWebResponse)

req.GetResponse();

// From the response, obtain an input stream.

Stream istrm = resp.GetResponseStream();

/* Now, read and display the html present at

the specified URI. So you can see what is

being displayed, the data is shown

400 characters at a time. After each 400

characters are displayed, you must press

ENTER to get the next 400. */

for(int i=1; ; i++) {

ch = istrm.ReadByte();

if(ch == -1) break;

Console.Write((char) ch);

if((i%400)==0) {

Console.Write("\nPress Enter.");

Console.ReadLine();

}

}

// Close the Response. This also closes istrm.

resp.Close();

} catch(WebException exc) {

Console.WriteLine("Network Error: " + exc.Message +

"\nStatus code: " + exc.Status);

} catch(ProtocolViolationException exc) {

Console.WriteLine("Protocol Error: " + exc.Message);

} catch(UriFormatException exc) {

Console.WriteLine("URI Format Error: " + exc.Message);

} catch(NotSupportedException exc) {

Console.WriteLine("Unknown Protocol: " + exc.Message);

} catch(IOException exc) {

Console.WriteLine("I/O Error: " + exc.Message);

} catch(System.Security.SecurityException exc) {

Console.WriteLine("Security Exception: " + exc.Message);

} catch(InvalidOperationException exc) {

Console.WriteLine("Invalid Operation: " + exc.Message);

}

}

}

listing 3

// Use Uri.

using System;

using System.Net;

class UriDemo {

public static void Main() {

Uri sample = new Uri("http://MySite.com/somefile.txt?SomeQuery");

Console.WriteLine("Host: " + sample.Host);

Console.WriteLine("Port: " + sample.Port);

Console.WriteLine("Scheme: " + sample.Scheme);

Console.WriteLine("Local Path: " + sample.LocalPath);

Console.WriteLine("Query: " + sample.Query);

Console.WriteLine("Path and query: " + sample.PathAndQuery);

}

}

listing 4

// Examine the headers.

using System;

using System.Net;

class HeaderDemo {

public static void Main() {

// Create a WebRequest to a URI.

HttpWebRequest req = (HttpWebRequest)

WebRequest.Create("http://www.McGraw-Hill.com");

// Send that request and return the response.

HttpWebResponse resp = (HttpWebResponse)

req.GetResponse();

// Obtain a list of the names.

string[] names = resp.Headers.AllKeys;

// Display the header name/value pairs.

Console.WriteLine("{0,-20}{1}\n", "Name", "Value");

foreach(string n in names)

Console.WriteLine("{0,-20}{1}", n, resp.Headers
);

// Close the Response.

resp.Close();

}

}

listing 5

/* Examine Cookies.

To see what cookies a web site uses,

specify its name on the command line.

For example, if you call this program

CookieDemo, then

CookieDemo http://msn.com

displays the cookies associated with msn.com.

*/

using System;

using System.Net;

class CookieDemo {

public static void Main(string[] args) {

if(args.Length != 1) {

Console.WriteLine("Usage: CookieDemo <uri>");

return ;

}

// Create a WebRequest to the specified URI.

HttpWebRequest req = (HttpWebRequest)

WebRequest.Create(args[0]);

// Get an empty cookie container.

req.CookieContainer = new CookieContainer();

// Send the request and return the response.

HttpWebResponse resp = (HttpWebResponse)

req.GetResponse();

// Display the cookies.

Console.WriteLine("Number of cookies: " +

resp.Cookies.Count);

Console.WriteLine("{0,-20}{1}", "Name", "Value");

for(int i=0; i < resp.Cookies.Count; i++)

Console.WriteLine("{0, -20}{1}",

resp.Cookies[i].Name,

resp.Cookies[i].Value);

// Close the Response.

resp.Close();

}

}

listing 6

/* Use LastModified.

To see the date on which a web site was

last modified, enter its URI on the command

line. For example, if you call this program

LastModified, then see the date of last

modification for HerbSchildt.com enter

LastModifiedDemo http://HerbSchildt.com

*/

using System;

using System.Net;

class LastModifiedDemo {

public static void Main(string[] args) {

if(args.Length != 1) {

Console.WriteLine("Usage: LastModifiedDemo <uri>");

return ;

}

HttpWebRequest req = (HttpWebRequest)

WebRequest.Create(args[0]);

HttpWebResponse resp = (HttpWebResponse)

req.GetResponse();

Console.WriteLine("Last modified: " + resp.LastModified);

resp.Close();

}

}

listing 7

/* MiniCrawler: A skeletal Web crawler.

Usage:

To start crawling, specify a starting

URI on the command line. For example,

to start at McGraw-Hill.com use this

command line:

MiniCrawler http://McGraw-Hill.com

*/

using System;

using System.Net;

using System.IO;

class MiniCrawler {

// Find a link in a content string.

static string FindLink(string htmlstr,

ref int startloc) {

int i;

int start, end;

string uri = null;

string lowcasestr = htmlstr.ToLower();

i = lowcasestr.IndexOf("href=\"http", startloc);

if(i != -1) {

start = htmlstr.IndexOf('"', i) + 1;

end = htmlstr.IndexOf('"', start);

uri = htmlstr.Substring(start, end-start);

startloc = end;

}

return uri;

}

public static void Main(string[] args) {

string link = null;

string str;

string answer;

int curloc; // holds current location in response

if(args.Length != 1) {

Console.WriteLine("Usage: MiniCrawler <uri>");

return ;

}

string uristr = args[0]; // holds current URI

try {

do {

Console.WriteLine("Linking to " + uristr);

// Create a WebRequest to the specified URI.

HttpWebRequest req = (HttpWebRequest)

WebRequest.Create(uristr);

uristr = null; // disallow further use of this URI

// Send that request and return the response.

HttpWebResponse resp = (HttpWebResponse)

req.GetResponse();

// From the response, obtain an input stream.

Stream istrm = resp.GetResponseStream();

// Wrap the input stream in a StreamReader.

StreamReader rdr = new StreamReader(istrm);

// Read in the entire page.

str = rdr.ReadToEnd();

curloc = 0;

do {

// Find the next URI to link to.

link = FindLink(str, ref curloc);

if(link != null) {

Console.WriteLine("Link found: " + link);

Console.Write("Link, More, Quit?");

answer = Console.ReadLine();

if(string.Compare(answer, "L", true) == 0) {

uristr = string.Copy(link);

break;

} else if(string.Compare(answer, "Q", true) == 0) {

break;

} else if(string.Compare(answer, "M", true) == 0) {

Console.WriteLine("Searching for another link.");

}

} else {

Console.WriteLine("No link found.");

break;

}

} while(link.Length > 0);

// Close the Response.

resp.Close();

} while(uristr != null);

} catch(WebException exc) {

Console.WriteLine("Network Error: " + exc.Message +

"\nStatus code: " + exc.Status);

} catch(ProtocolViolationException exc) {

Console.WriteLine("Protocol Error: " + exc.Message);

} catch(UriFormatException exc) {

Console.WriteLine("URI Format Error: " + exc.Message);

} catch(NotSupportedException exc) {

Console.WriteLine("Unknown Protocol: " + exc.Message);

} catch(IOException exc) {

Console.WriteLine("I/O Error: " + exc.Message);

}

Console.WriteLine("Terminating MiniCrawler.");

}

}

listing 8

// Use WebClient to download information into a file.

using System;

using System.Net;

using System.IO;

class WebClientDemo {

public static void Main() {

WebClient user = new WebClient();

string uri = "http://www.McGraw-Hill.com";

string fname = "data.txt";

try {

Console.WriteLine("Downloading data from " +

uri + " to " + fname);

user.DownloadFile(uri, fname);

} catch (WebException exc) {

Console.WriteLine(exc);

}

Console.WriteLine("Download complete.");

}

}

listing 1

// A simple Cipher component. Call this file CipherLib.cs.

using System.ComponentModel;

namespace CipherLib { // put component in its own namespace

// Notice that CipherComp inherits Component.

public class CipherComp : Component {

// Encode a string.

public string Encode(string msg) {

string temp = "";

for(int i=0; i < msg.Length; i++)

temp += (char) (msg[i] + 1);

return temp;

}

// Decode a string.

public string Decode(string msg) {

string temp = "";

for(int i=0; i < msg.Length; i++)

temp += (char) (msg[i] - 1);

return temp;

}

}

}

listing 2

// A client that uses CipherComp.

using System;

using CipherLib; // import CipherComp's namespace

class CipherCompClient {

public static void Main() {

CipherComp cc = new CipherComp();

string text = "This is a test";

string ciphertext = cc.Encode(text);

Console.WriteLine(ciphertext);

string plaintext = cc.Decode(ciphertext);

Console.WriteLine(plaintext);

cc.Dispose(); // free resources

}

}

listing 3

// A skeletal implementation of a component that uses Dispose(bool).

class MyComp : Component {

bool isDisposed; // true if component is disposed

public MyComp {

isDispose = false;

// ...

}

~MyComp() {

Dispose(false);

}

protected override void Dispose(bool dispAll) {

if(!isDisposed) {

if(dispAll) {

// release managed resources here

isDisposed = true; // set component to disposed

}

// release unmanaged resources here

base.Dispose(dispAll);

}

}

}

listing 4

// An enhanced cipher component that maintains a log file.

using System;

using System.ComponentModel;

using System.IO;

namespace CipherLib {

// An Cipher component that maintains a log file.

public class CipherComp : Component {

static int useID = 0;

int id; // instance id

bool isDisposed; // true if component is disposed.

FileStream log;

// Constructor

public CipherComp() {

isDisposed = false; // component not disposed

try {

log = new FileStream("CipherLog" + useID, FileMode.Create);

id = useID;

useID++;

} catch (FileNotFoundException exc) {

Console.WriteLine(exc);

log = null;

}

}

// Destructor

~CipherComp() {

Console.WriteLine("Destructor for component "

+ id);

Dispose(false);

}

// Encode the file. Return and store result.

public string Encode(string msg) {

string temp = "";

for(int i=0;i < msg.Length; i++)

temp += (char) (msg[i] + 1);

// Store in log file.

for(int i=0; i < temp.Length; i++)

log.WriteByte((byte) temp[i]);

return temp;

}

// Decode the message. Return and store result.

public string Decode(string msg) {

string temp = "";

for(int i=0; i < msg.Length; i++)

temp += (char) (msg[i] - 1);

// Store in log file.

for(int i=0; i < temp.Length; i++)

log.WriteByte((byte) temp[i]);

return temp;

}

protected override void Dispose(bool dispAll) {

Console.WriteLine("Dispose(" + dispAll +

") for component " + id);

if(!isDisposed) {

if(dispAll) {

Console.WriteLine("Closing file for " +

"component " + id);

log.Close(); // close encoded file

isDisposed = true;

}

// no unmanaged resources to release

base.Dispose(dispAll);

}

}

}

}

listing 5

// Another client that uses CipherComp.

using System;

using CipherLib; // import CipherComp's namespace

class CipherCompClient {

public static void Main() {

CipherComp cc = new CipherComp();

string text = "Testing";

string ciphertext = cc.Encode(text);

Console.WriteLine(ciphertext);

string plaintext = cc.Decode(ciphertext);

Console.WriteLine(plaintext);

text = "Components are powerful.";

ciphertext = cc.Encode(text);

Console.WriteLine(ciphertext);

plaintext = cc.Decode(ciphertext);

Console.WriteLine(plaintext);

cc.Dispose(); // free resources

}

}

listing 6

// Encode the file. Return and store result.

public string Encode(string msg) {

// Prevent use of a disposed component.

if(isDisposed) {

Console.WriteLine("Error: Component disposed.");

return null;

}

string temp = "";

for(int i=0;i < msg.Length; i++)

temp += (char) (msg[i] + 1);

// Store in log file.

for(int i=0; i < temp.Length; i++)

log.WriteByte((byte) temp[i]);

return temp;

}

// Decode the message. Return and store result.

public string Decode(string msg) {

// Prevent use of a disposed component.

if(isDisposed) {

Console.WriteLine("Error: Component disposed.");

return null;

}

string temp = "";

for(int i=0; i < msg.Length; i++)

temp += (char) (msg[i] - 1);

// Store in log file.

for(int i=0; i < temp.Length; i++)

log.WriteByte((byte) temp[i]);

return temp;

}

listing 7

// Employ the using statement.

using System;

using CipherLib; // import CipherComp's namespace

class CipherCompClient {

public static void Main() {

// cc will be disposed when this block ends.

using(CipherComp cc = new CipherComp()) {

string text = "The using statement.";

string ciphertext = cc.Encode(text);

Console.WriteLine(ciphertext);

string plaintext = cc.Decode(ciphertext);

Console.WriteLine(plaintext);

}

}

}

listing 8

// Demonstrate a component container.

using System;

using System.ComponentModel;

using CipherLib; // import CipherComp's namespace

class UseContainer {

public static void Main(string[] args) {

string str = "Using containers.";

Container cont = new Container();

CipherComp cc = new CipherComp();

CipherComp cc2 = new CipherComp();

cont.Add(cc);

cont.Add(cc2, "Second Component");

Console.WriteLine("First message: " + str);

str = cc.Encode(str);

Console.WriteLine("First message encoded: " +

str);

str = cc.Decode(str);

Console.WriteLine("First message decoded: " +

str);

str = "one, two, three";

Console.WriteLine("Second message: " + str);

str = cc2.Encode(str);

Console.WriteLine("Second message encoded: " +

str);

str = cc2.Decode(str);

Console.WriteLine("Second message decoded: " +

str);

Console.WriteLine("\ncc2's name: " + cc2.Site.Name);

Console.WriteLine();

// Release both components.

cont.Dispose();

}

}

listing 1

// A form-based Windows Skeleton.

using System;

using System.Windows.Forms;

// WinSkel is derived from Form.

class WinSkel : Form {

public WinSkel() {

// Give the window a name.

Text = "A Windows Skeleton";

}

// Main is used only to start the application.

[STAThread]

public static void Main() {

WinSkel skel = new WinSkel(); // create a form

// Start the window running.

Application.Run(skel);

}

}

listing 2

// Add a Button.

using System;

using System.Windows.Forms;

using System.Drawing;

class ButtonForm : Form {

Button MyButton = new Button();

public ButtonForm() {

Text = "Using a Button";

MyButton = new Button();

MyButton.Text = "Press Here";

MyButton.Location = new Point(100, 200);

Controls.Add(MyButton);

}

[STAThread]

public static void Main() {

ButtonForm skel = new ButtonForm();

Application.Run(skel);

}

}

listing 3

// Handle button messages.

using System;

using System.Windows.Forms;

using System.Drawing;

class ButtonForm : Form {

Button MyButton = new Button();

public ButtonForm() {

Text = "Respond to a Button";

MyButton = new Button();

MyButton.Text = "Press Here";

MyButton.Location = new Point(100, 200);

// Add button event handler to list.

MyButton.Click += MyButtonClick;

Controls.Add(MyButton);

}

[STAThread]

public static void Main() {

ButtonForm skel = new ButtonForm();

Application.Run(skel);

}

// Handler for MyButton.

protected void MyButtonClick(object who, EventArgs e) {

if(MyButton.Top == 200)

MyButton.Location = new Point(10, 10);

else

MyButton.Location = new Point(100, 200);

}

}

listing 4

// An Alternative button handler.

protected void MyButtonClick(object who, EventArgs e) {

Button b = (Button) who;

if(b.Top == 200)

b.Location = new Point(10, 10);

else

b.Location = new Point(100, 200);

}

listing 5

// Add a stop button.

using System;

using System.Windows.Forms;

using System.Drawing;

class ButtonForm : Form {

Button MyButton;

Button StopButton;

public ButtonForm() {

Text = "Adding a Stop Button";

// Create the buttons.

MyButton = new Button();

MyButton.Text = "Press Here";

MyButton.Location = new Point(100, 200);

StopButton = new Button();

StopButton.Text = "Stop";

StopButton.Location = new Point(100, 100);

// Add the button event handlers to the window.

MyButton.Click += MyButtonClick;

Controls.Add(MyButton);

StopButton.Click += StopButtonClick;

Controls.Add(StopButton);

}

[STAThread]

public static void Main() {

ButtonForm skel = new ButtonForm();

Application.Run(skel);

}

// Handler for MyButton.

protected void MyButtonClick(object who, EventArgs e) {

if(MyButton.Top == 200)

MyButton.Location = new Point(10, 10);

else

MyButton.Location = new Point(100, 200);

}

// Handler for StopButton.

protected void StopButtonClick(object who, EventArgs e) {

// If users answers Yes, terminate the program.

DialogResult result = MessageBox.Show("Stop Program?",

"Terminate",

MessageBoxButtons.YesNo);

if(result == DialogResult.Yes) Application.Exit();

}

}

listing 6

// Add a Main Menu.

using System;

using System.Windows.Forms;

class MenuForm : Form {

MainMenu MyMenu;

public MenuForm() {

Text = "Adding a Main Menu";

// Create a main menu object.

MyMenu = new MainMenu();

// Add top-level menu items to the menu.

MenuItem m1 = new MenuItem("File");

MyMenu.MenuItems.Add(m1);

MenuItem m2 = new MenuItem("Tools");

MyMenu.MenuItems.Add(m2);

// Create File submenu

MenuItem subm1 = new MenuItem("Open");

m1.MenuItems.Add(subm1);

MenuItem subm2 = new MenuItem("Close");

m1.MenuItems.Add(subm2);

MenuItem subm3 = new MenuItem("Exit");

m1.MenuItems.Add(subm3);

// Create Tools submenu

MenuItem subm4 = new MenuItem("Coordinates");

m2.MenuItems.Add(subm4);

MenuItem subm5 = new MenuItem("Change Size");

m2.MenuItems.Add(subm5);

MenuItem subm6 = new MenuItem("Restore");

m2.MenuItems.Add(subm6);

// Add event handlers for the menu items.

subm1.Click += MMOpenClick;

subm2.Click += MMCloseClick;

subm3.Click += MMExitClick;

subm4.Click += MMCoordClick;

subm5.Click += MMChangeClick;

subm6.Click += MMRestoreClick;

// Assign the menu to the form.

Menu = MyMenu;

}

[STAThread]

public static void Main() {

MenuForm skel = new MenuForm();

Application.Run(skel);

}

// Handler for main menu Coordinates selection.

protected void MMCoordClick(object who, EventArgs e) {

// Create a string that contains the coordinates.

string size =

String.Format("{0}: {1}, {2}\n{3}: {4}, {5} ",

"Top, Left", Top, Left,

"Bottom, Right", Bottom, Right);

// Display a message box.

MessageBox.Show(size, "Window Coordinates",

MessageBoxButtons.OK);

}

// Handler for main menu Change selection.

protected void MMChangeClick(object who, EventArgs e) {

Width = Height = 200;

}

// Handler for main menu Restore selection.

protected void MMRestoreClick(object who, EventArgs e) {

Width = Height = 300;

}

// Handler for main menu Open selection.

protected void MMOpenClick(object who, EventArgs e) {

MessageBox.Show("Inactive", "Inactive",

MessageBoxButtons.OK);

}

// Handler for main menu Open selection.

protected void MMCloseClick(object who, EventArgs e) {

MessageBox.Show("Inactive", "Inactive",

MessageBoxButtons.OK);

}

// Handler for main menu Exit selection.

protected void MMExitClick(object who, EventArgs e) {

DialogResult result = MessageBox.Show("Stop Program?",

"Terminate",

MessageBoxButtons.YesNo);

if(result == DialogResult.Yes) Application.Exit();

}

}

listing 7

// Use a MenuStrip.

using System;

using System.Windows.Forms;

class MenuForm : Form {

MenuStrip MyMenu; // use a MenuStrip

public MenuForm() {

Text = "Use a MenuStrip";

// Create a main menu object.

MyMenu = new MenuStrip();

// Add top-level menu items to the menu.

ToolStripMenuItem m1 = new ToolStripMenuItem("File");

MyMenu.Items.Add(m1);

ToolStripMenuItem m2 = new ToolStripMenuItem("Tools");

MyMenu.Items.Add(m2);

// Create File submenu

ToolStripMenuItem subm1 = new ToolStripMenuItem("Open");

m1.DropDownItems.Add(subm1);

ToolStripMenuItem subm2 = new ToolStripMenuItem("Close");

m1.DropDownItems.Add(subm2);

ToolStripMenuItem subm3 = new ToolStripMenuItem("Exit");

m1.DropDownItems.Add(subm3);

// Create Tools submenu

ToolStripMenuItem subm4 = new ToolStripMenuItem("Coordinates");

m2.DropDownItems.Add(subm4);

ToolStripMenuItem subm5 = new ToolStripMenuItem("Change Size");

m2.DropDownItems.Add(subm5);

ToolStripMenuItem subm6 = new ToolStripMenuItem("Restore");

m2.DropDownItems.Add(subm6);

// Add event handlers for the menu items.

subm1.Click += MMOpenClick;

subm2.Click += MMCloseClick;

subm3.Click += MMExitClick;

subm4.Click += MMCoordClick;

subm5.Click += MMChangeClick;

subm6.Click += MMRestoreClick;

// Add to list of controls.

Controls.Add(MyMenu);

// Assign the menu to the form.

MainMenuStrip = MyMenu;

}

[STAThread]

public static void Main() {

MenuForm skel = new MenuForm();

// Enable visual styles for Windows XP.

Application.EnableVisualStyles();

Application.Run(skel);

}

// Handler for main menu Coordinates selection.

protected void MMCoordClick(object who, EventArgs e) {

// Create a string that contains the coordinates.

string size =

String.Format("{0}: {1}, {2}\n{3}: {4}, {5} ",

"Top, Left", Top, Left,

"Bottom, Right", Bottom, Right);

// Display a message box.

MessageBox.Show(size, "Window Coordinates",

MessageBoxButtons.OK);

}

// Handler for main menu Change selection.

protected void MMChangeClick(object who, EventArgs e) {

Width = Height = 200;

}

// Handler for main menu Restore selection.

protected void MMRestoreClick(object who, EventArgs e) {

Width = Height = 300;

}

// Handler for main menu Open selection.

protected void MMOpenClick(object who, EventArgs e) {

MessageBox.Show("Inactive", "Inactive",

MessageBoxButtons.OK);

}

// Handler for main menu Open selection.

protected void MMCloseClick(object who, EventArgs e) {

MessageBox.Show("Inactive", "Inactive",

MessageBoxButtons.OK);

}

// Handler for main menu Exit selection.

protected void MMExitClick(object who, EventArgs e) {

DialogResult result = MessageBox.Show("Stop Program?",

"Terminate",

MessageBoxButtons.YesNo);

if(result == DialogResult.Yes) Application.Exit();

}

}

listing 1

/*

This module contains the recursive descent

parser that does not use variables.

*/

using System;

// Exception class for parser errors.

class ParserException : ApplicationException {

public ParserException(string str) : base(str) { }

public override string ToString() {

return Message;

}

}

class Parser {

// Enumerate token types.

enum Types { NONE, DELIMITER, VARIABLE, NUMBER };

// Enumerate error types.

enum Errors { SYNTAX, UNBALPARENS, NOEXP, DIVBYZERO };

string exp; // refers to expression string

int expIdx; // current index into the expression

string token; // holds current token

Types tokType; // holds token's type

// Parser entry point.

public double Evaluate(string expstr)

{

double result;

exp = expstr;

expIdx = 0;

try {

GetToken();

if(token == "") {

SyntaxErr(Errors.NOEXP); // no expression present

return 0.0;

}

EvalExp2(out result);

if(token != "") // last token must be null

SyntaxErr(Errors.SYNTAX);

return result;

} catch (ParserException exc) {

// Add other error handling here, as desired.

Console.WriteLine(exc);

return 0.0;

}

}

// Add or subtract two terms.

void EvalExp2(out double result)

{

string op;

double partialResult;

EvalExp3(out result);

while((op = token) == "+" || op == "-") {

GetToken();

EvalExp3(out partialResult);

switch(op) {

case "-":

result = result - partialResult;

break;

case "+":

result = result + partialResult;

break;

}

}

}

// Multiply or divide two factors.

void EvalExp3(out double result)

{

string op;

double partialResult = 0.0;

EvalExp4(out result);

while((op = token) == "*" ||

op == "/" || op == "%") {

GetToken();

EvalExp4(out partialResult);

switch(op) {

case "*":

result = result * partialResult;

break;

case "/":

if(partialResult == 0.0)

SyntaxErr(Errors.DIVBYZERO);

result = result / partialResult;

break;

case "%":

if(partialResult == 0.0)

SyntaxErr(Errors.DIVBYZERO);

result = (int) result % (int) partialResult;

break;

}

}

}

// Process an exponent.

void EvalExp4(out double result)

{

double partialResult, ex;

int t;

EvalExp5(out result);

if(token == "^") {

GetToken();

EvalExp4(out partialResult);

ex = result;

if(partialResult == 0.0) {

result = 1.0;

return;

}

for(t=(int)partialResult-1; t > 0; t--)

result = result * (double)ex;

}

}

// Evaluate a unary + or -.

void EvalExp5(out double result)

{

string op;

op = "";

if((tokType == Types.DELIMITER) &&

token == "+" || token == "-") {

op = token;

GetToken();

}

EvalExp6(out result);

if(op == "-") result = -result;

}

// Process a parenthesized expression.

void EvalExp6(out double result)

{

if((token == "(")) {

GetToken();

EvalExp2(out result);

if(token != ")")

SyntaxErr(Errors.UNBALPARENS);

GetToken();

}

else Atom(out result);

}

// Get the value of a number.

void Atom(out double result)

{

switch(tokType) {

case Types.NUMBER:

try {

result = Double.Parse(token);

} catch (FormatException) {

result = 0.0;

SyntaxErr(Errors.SYNTAX);

}

GetToken();

return;

default:

result = 0.0;

SyntaxErr(Errors.SYNTAX);

break;

}

}

// Handle a syntax error.

void SyntaxErr(Errors error)

{

string[] err = {

"Syntax Error",

"Unbalanced Parentheses",

"No Expression Present",

"Division by Zero"

};

throw new ParserException(err[(int)error]);

}

// Obtain the next token.

void GetToken()

{

tokType = Types.NONE;

token = "";

if(expIdx == exp.Length) return; // at end of expression

// skip over white space

while(expIdx < exp.Length &&

Char.IsWhiteSpace(exp[expIdx])) ++expIdx;

// trailing whitespace ends expression

if(expIdx == exp.Length) return;

if(IsDelim(exp[expIdx])) { // is operator

token += exp[expIdx];

expIdx++;

tokType = Types.DELIMITER;

}

else if(Char.IsLetter(exp[expIdx])) { // is variable

while(!IsDelim(exp[expIdx])) {

token += exp[expIdx];

expIdx++;

if(expIdx >= exp.Length) break;

}

tokType = Types.VARIABLE;

}

else if(Char.IsDigit(exp[expIdx])) { // is number

while(!IsDelim(exp[expIdx])) {

token += exp[expIdx];

expIdx++;

if(expIdx >= exp.Length) break;

}

tokType = Types.NUMBER;

}

}

// Return true if c is a delimiter.

bool IsDelim(char c)

{

if((" +-/*%^=()".IndexOf(c) != -1))

return true;

return false;

}

}

listing 2

// Demonstrate the parser.

using System;

class ParserDemo {

public static void Main()

{

string expr;

Parser p = new Parser();

Console.WriteLine("Enter an empty expression to stop.");

for(;;) {

Console.Write("Enter expression: ");

expr = Console.ReadLine();

if(expr == "") break;

Console.WriteLine("Result: " + p.Evaluate(expr));

}

}

}

listing 3

/*

This module contains the recursive descent

parser that recognizes variables.

*/

using System;

// Exception class for parser errors.

class ParserException : ApplicationException {

public ParserException(string str) : base(str) { }

public override string ToString() {

return Message;

}

}

class Parser {

// Enumerate token types.

enum Types { NONE, DELIMITER, VARIABLE, NUMBER };

// Enumerate error types.

enum Errors { SYNTAX, UNBALPARENS, NOEXP, DIVBYZERO };

string exp; // refers to expression string

int expIdx; // current index into the expression

string token; // holds current token

Types tokType; // holds token's type

// Array for variables.

double[] vars = new double[26];

public Parser() {

// Initialize the variables to zero.

for(int i=0; i < vars.Length; i++)

vars[i] = 0.0;

}

// Parser entry point.

public double Evaluate(string expstr)

{

double result;

exp = expstr;

expIdx = 0;

try {

GetToken();

if(token == "") {

SyntaxErr(Errors.NOEXP); // no expression present

return 0.0;

}

EvalExp1(out result); // now, call EvalExp1() to start

if(token != "") // last token must be null

SyntaxErr(Errors.SYNTAX);

return result;

} catch (ParserException exc) {

// Add other error handling here, as desired.

Console.WriteLine(exc);

return 0.0;

}

}

// Process an assignment.

void EvalExp1(out double result)

{

int varIdx;

Types ttokType;

string temptoken;

if(tokType == Types.VARIABLE) {

// save old token

temptoken = String.Copy(token);

ttokType = tokType;

// Compute the index of the variable.

varIdx = Char.ToUpper(token[0]) - 'A';

GetToken();

if(token != "=") {

PutBack(); // return current token

// restore old token -- not an assignment

token = String.Copy(temptoken);

tokType = ttokType;

}

else {

GetToken(); // get next part of exp

EvalExp2(out result);

vars[varIdx] = result;

return;

}

}

EvalExp2(out result);

}

// Add or subtract two terms.

void EvalExp2(out double result)

{

string op;

double partialResult;

EvalExp3(out result);

while((op = token) == "+" || op == "-") {

GetToken();

EvalExp3(out partialResult);

switch(op) {

case "-":

result = result - partialResult;

break;

case "+":

result = result + partialResult;

break;

}

}

}

// Multiply or divide two factors.

void EvalExp3(out double result)

{

string op;

double partialResult = 0.0;

EvalExp4(out result);

while((op = token) == "*" ||

op == "/" || op == "%") {

GetToken();

EvalExp4(out partialResult);

switch(op) {

case "*":

result = result * partialResult;

break;

case "/":

if(partialResult == 0.0)

SyntaxErr(Errors.DIVBYZERO);

result = result / partialResult;

break;

case "%":

if(partialResult == 0.0)

SyntaxErr(Errors.DIVBYZERO);

result = (int) result % (int) partialResult;

break;

}

}

}

// Process an exponent.

void EvalExp4(out double result)

{

double partialResult, ex;

int t;

EvalExp5(out result);

if(token == "^") {

GetToken();

EvalExp4(out partialResult);

ex = result;

if(partialResult == 0.0) {

result = 1.0;

return;

}

for(t=(int)partialResult-1; t > 0; t--)

result = result * (double)ex;

}

}

// Evaluate a unary + or -.

void EvalExp5(out double result)

{

string op;

op = "";

if((tokType == Types.DELIMITER) &&

token == "+" || token == "-") {

op = token;

GetToken();

}

EvalExp6(out result);

if(op == "-") result = -result;

}

// Process a parenthesized expression.

void EvalExp6(out double result)

{

if((token == "(")) {

GetToken();

EvalExp2(out result);

if(token != ")")

SyntaxErr(Errors.UNBALPARENS);

GetToken();

}

else Atom(out result);

}

// Get the value of a number or variable.

void Atom(out double result)

{

switch(tokType) {

case Types.NUMBER:

try {

result = Double.Parse(token);

} catch (FormatException) {

result = 0.0;

SyntaxErr(Errors.SYNTAX);

}

GetToken();

return;

case Types.VARIABLE:

result = FindVar(token);

GetToken();

return;

default:

result = 0.0;

SyntaxErr(Errors.SYNTAX);

break;

}

}

// Return the value of a variable.

double FindVar(string vname)

{

if(!Char.IsLetter(vname[0])){

SyntaxErr(Errors.SYNTAX);

return 0.0;

}

return vars[Char.ToUpper(vname[0])-'A'];

}

// Return a token to the input stream.

void PutBack()

{

for(int i=0; i < token.Length; i++) expIdx--;

}

// Handle a syntax error.

void SyntaxErr(Errors error)

{

string[] err = {

"Syntax Error",

"Unbalanced Parentheses",

"No Expression Present",

"Division by Zero"

};

throw new ParserException(err[(int)error]);

}

// Obtain the next token.

void GetToken()

{

tokType = Types.NONE;

token = "";

if(expIdx == exp.Length) return; // at end of expression

// skip over white space

while(expIdx < exp.Length &&

Char.IsWhiteSpace(exp[expIdx])) ++expIdx;

// trailing whitespace ends expression

if(expIdx == exp.Length) return;

if(IsDelim(exp[expIdx])) { // is operator

token += exp[expIdx];

expIdx++;

tokType = Types.DELIMITER;

}

else if(Char.IsLetter(exp[expIdx])) { // is variable

while(!IsDelim(exp[expIdx])) {

token += exp[expIdx];

expIdx++;

if(expIdx >= exp.Length) break;

}

tokType = Types.VARIABLE;

}

else if(Char.IsDigit(exp[expIdx])) { // is number

while(!IsDelim(exp[expIdx])) {

token += exp[expIdx];

expIdx++;

if(expIdx >= exp.Length) break;

}

tokType = Types.NUMBER;

}

}

// Return true if c is a delimiter.

bool IsDelim(char c)

{

if((" +-/*%^=()".IndexOf(c) != -1))

return true;

return false;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: