0% found this document useful (0 votes)
78 views134 pages

C# Arraays

Arrays allow storing multiple values of the same type together in memory. In C#, arrays can be declared as fixed length or dynamic. A fixed length array has a predefined size while a dynamic array can grow in size as new items are added. Arrays are declared with the type, followed by square brackets and the array name. The new operator is used to instantiate the array and allocate memory. Individual items in the array are accessed via an index with the first item at index 0.

Uploaded by

MEENU Teotia
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
Download as pptx, pdf, or txt
0% found this document useful (0 votes)
78 views134 pages

C# Arraays

Arrays allow storing multiple values of the same type together in memory. In C#, arrays can be declared as fixed length or dynamic. A fixed length array has a predefined size while a dynamic array can grow in size as new items are added. Arrays are declared with the type, followed by square brackets and the array name. The new operator is used to instantiate the array and allocate memory. Individual items in the array are accessed via an index with the first item at index 0.

Uploaded by

MEENU Teotia
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1/ 134

Arrays

STRUCT
 A struct is a simple user-defined type, a lightweight alternative to a class.
 Structs are similar to classes in that they may contain constructors,
properties, methods, fields, operators, nested types, and indexers.
 There are also significant differences between classes and structs.
 For instance, structs don’t support inheritance or destructors.
 More important, although a class is a reference type, a struct is a value type.
 Thus, structs are useful for representing objects that don’t require reference
semantics.
C++ programmers take note: the meaning of C#’s struct construct
is very different from C++’s.
In C++, a struct is exactly like a class, except that the visibility
(public versus private) is different by default.
In C#, structs are value types, whereas classes are reference types,
and C# structs have other limitations
 if you have a class that has, as its member variables, 10 structs instead of 10
objects, when that class is created on the heap, one big object is created (the
class with its 10 structs) rather than 11 objects.
 That allows the garbage collector to do much less work when your
containing class is ready to be destroyed, making your program more
efficient.
 If you have a lot of classes like that, and you create and destroy them
frequently, the performance differences can begin to be noticeable.
 The syntax for declaring a struct is almost identical to that for a class:
[attributes] [access-modifiers] struct identifier [:interface-list]
{ struct-members }
 No destructor or custom default constructor Structs can’t have destructors,
nor can they have a custom parameterless (default) constructor;
 however, the CLR will initialize your structure and zero out all the fields if
your object is called as though it had a default constructor.
 No initialization
 You can’t initialize an instance field in a struct. Thus, it is illegal to write:
private int xVal = 50;
private int yVal = 100;
 though that would have been fine had this been a class.
 Structs are designed to be simple and lightweight.
Encapsulating Data with Properties
 Properties allow clients to access class state as though they were accessing
member fields directly, while actually implementing that access through a
class method.
 This is ideal. The client wants direct access to the state of the object and
doesn’t want to work with methods.
 The class designer, however, wants to hide the internal state of his class in
class members, and provide indirect access through a method.
Properties meet both goals:
 they provide a simple interface to the client, appearing to be a member
variable.
 They are implemented as methods, however, providing the data-hiding
required by good object-oriented design
 To declare a property, write the property type and name followed by a pair of
braces.
 Within the braces you may declare get and set accessors.
 Neither of these has explicit parameters, though the set( ), accessor has an
implicit parameter value.
 Hour is a property. Its declaration creates two accessors: get and set:
public int Hour
{
get
{
return hour;
}
set
{
hour = value;
}
}
Each accessor has an accessor body that does the work of retrieving
and setting the property value.
The property value might be stored in a database (in which case the
accessor body would do whatever work is needed to interact with
the database), or it might just be stored in a private member
variable:
private int hour;
The set Accessor
 The set accessor sets the value of a property and is similar to a method that
returns void.
 When you define a set accessor, you must use the value keyword to represent
the argument whose value is passed to and stored by the property:
set
{
hour = value;
}
 Here, again, a private member variable is used to store the value of the
property, but the set accessor could write to a database or update other
member variables as needed.
 When you assign a value to the property, the set accessor is automatically
invoked, and the implicit parameter value is set to the value you assign:
theHour++;
t.Hour = theHour;
 The two main advantages of this approach are that the client can interact with
the properties directly, without sacrificing the data-hiding and encapsulation
in good object-oriented design, and that the author of the property can ensure
that the data provided is valid.
Property Access Modifiers
 It is possible to set an access modifier (protected, internal, private) to modify
access to either the get or set accessor.
 To do so, your property must have both a set and a get accessor, and you may
modify only one or the other.
 Also, the modifier must be more restrictive than the accessibility level
already on the property or the indexer (thus, you may add protected to the get
or set accessor of a public property, but not to a private property):
public string MyString
{
protected get { return myString; }
set { myString = value; }
}
 access to the get accessor is restricted to methods of this class and classes
derived from this class, whereas the set accessor is publicly visible.
readonly Fields
 You might want to create a version of the Time class that is responsible for
providing public static values representing the current time and date.
 As the example shows, the RightNow.Year value can be changed, for example,
to 2008.
 This is clearly not what we’d like. You’d like to mark the static values as
constant, but that is not possible because you don’t initialize them until the
static constructor is executed.
 C# provides the keyword readonly for exactly this purpose. If you change the
class member variable declarations as follows:
public static readonly int Year;
public static readonly int Month;
public static readonly int Date;
public static readonly int Hour;
public static readonly int Minute;
public static readonly int Second;
and then comment out the reassignment in Main( ):
// RightNow.Year = 2008; // error!
Arrays
 An array is a collection of variables of the same type that are referred to by a
common name.
 In C#, arrays can have one or more dimensions, although the one-
dimensional array is the most common.
 Arrays are used for a variety of purposes because they offer a convenient
means of grouping together related variables.
 For example, you might use an array to hold a record of the daily high
temperature for a month, a list of stock prices, or your collection of
programming books.
 The principal advantage of an array is that it organizes data in such a way
that it can be easily manipulated.
 For example, if you have an array containing the dividends for a selected
group of stocks, it is easy to compute the average income by cycling through
the array.
 Also, arrays organize data in such a way that it can be easily sorted.
Arrays represent a set of items all belonging to the same type.
The declaration itself may use a variable or a constant to define the
length of the array.
However, an array has a set length and it cannot be changed after
declaration.
C# provides native syntax for the declaration of Arrays. What is
actually created, however, is an object of type System.Array.*
Arrays in C# thus provide you with the best of both worlds: easy-
to-use C-style syntax underpinned with an actual class definition so
that instances of an array have access to the methods and properties
of System.Array.
arrays can be declared as fixed length or dynamic.
A fixed length array can store a predefined number of items.
A dynamic array does not have a predefined size.
The size of a dynamic array increases as you add new items to the
array.
You can declare an array of fixed length or dynamic.
You can even change a dynamic array to static after it is defined.
The following code snippet defines the simplest dynamic array of
integer types that does not have a fixed size.
int[] intArray;
As you can see from the above code snippet, the declaration of an
array starts with a type of array followed by a square bracket ([])
and name of the array.
The following code snippet declares an array that can store 5 items
only starting from index 0 to 4.
int[] intArray;
intArray = new int[5];
The following code snippet declares an array that can store 100
items starting from index 0 to 99.
int[] intArray;
intArray = new int[100];
In C#, arrays are objects. That means that declaring an array doesn't
create an array. After declaring an array, you need to instantiate an
array by using the "new" operator.
The following code snippet defines arrays of double, char, bool, and
string data types.
double[] doubleArray = new double[5];
char[] charArray = new char[5];
bool[] boolArray = new bool[2];
string[] stringArray = new string[10];
Once an array is declared, the next step is to initialize an array. The
initialization process of an array includes adding actual data to the
array.
The following code snippet creates an array of 3 items and values
of these items are added when the array is initialized.
// Initialize a fixed array
int[] staticIntArray = new int[3] {1, 3, 5};
 Alternative, we can also add array items one at a time as listed in
the following code snippet.
 // Initialize a fixed array one item at a time
int[] staticIntArray = new int[3];
staticIntArray[0] = 1;
staticIntArray[1] = 3;
staticIntArray[2] = 5;
The following code snippet declares a dynamic array with string
values.
 // Initialize a dynamic array items during declaration
string[] strArray = new string[] { "Mahesh Chand", "Mike
Gold", "Raj Beniwal", "Praveen Kumar", "Dinesh Beniwal" };
We can access an array item by passing the item index in the array.
The following code snippet creates an array of three items and
displays those items on the console.
// Initialize a fixed array one item at a time
int[] staticIntArray = new int[3];
staticIntArray[0] = 1;
staticIntArray[1] = 3;
staticIntArray[2] = 5;
 // Read array items one by one
Console.WriteLine(staticIntArray[0]);
Console.WriteLine(staticIntArray[1]);
Console.WriteLine(staticIntArray[2]);
 This method is useful when you know what item you want to
access from an array. If you try to pass an item index greater than
the items in array, you will get an error.
The foreach control statement (loop) is used to iterate through the
items of an array. For example, the following code uses foreach
loop to read all items of an array of strings.
 // Initialize a dynamic array items during declaration
string[] strArray = new string[] { "Mahesh Chand", "Mike
Gold", "Raj Beniwal", "Praveen Kumar", "Dinesh Beniwal" };
 // Read array items using foreach loop
foreach (string str in strArray)
{
    Console.WriteLine(str);
}
This approach is used when you do not know the exact index of an
item in an array and needs to loop through all the items.
A multi dimension array is declared as following:
string[,] mutliDimStringArray;
A multi-dimensional array can be fixed-sized or dynamic sized.
Initializing multi-dimensional arrays
 The following code snippet is an example of fixed-sized multi-dimensional
arrays that defines two multi dimension arrays with a matrix of 3x2 and 2x2.
The first array can store 6 items and second array can store 4 items. Both of
these arrays are initialized during the declaration.
 int[,] numbers = new int[3, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 } };
 string[,] names = new string[2, 2] { { "Rosy", "Amy" },
{ "Peter", "Albert" } };
 examples of multi-dimensional dynamic arrays where you are not sure of the
number of items of the array. The following code snippet creates two multi-
dimensional arrays with no limit.
 int[,] numbers = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 } };
 string[,] names = new string[,] { { "Rosy", "Amy" }, { "Peter", "Albert" } };
You can also omit the new operator as we did in single dimension
arrays. You can assign these values directly without using the new
operator. For example:
int[,] numbers = { { 1, 2 }, { 3, 4 }, { 5, 6 } };
string[,] names = { { "Rosy", "Amy" }, { "Peter", "Albert" } };
 We can also initialize the array items one item at a time. The
following code snippet is an example of initializing array items one
at a time.
 int[,] numbers = new int[3, 2];
numbers[0, 0] = 1;
numbers[1, 0] = 2;
numbers[2, 0] = 3;
numbers[0, 1] = 4;
numbers[1, 1] = 5;
numbers[2, 1] = 6;
A multi-dimensional array items are represented in a matrix format
and to access it's items, we need to specify the matrix dimension.
For example, item(1,2) represents an array item in the matrix at
second row and third column.
The following code snippet shows how to access numbers array
defined in the above code.
Console.WriteLine(numbers[0,0]);
Console.WriteLine(numbers[0, 1]);
Console.WriteLine(numbers[1, 0]);
Console.WriteLine(numbers[1, 1]);
Console.WriteLine(numbers[2, 0]);
Console.WriteLine(numbers[2, 2]);
Jagged Arrays
 Jagged arrays are arrays of arrays. The elements of a jagged array are other
arrays.
Declaring Jagged Arrays
 Declaration of a jagged array involves two brackets. For example, the
following code snippet declares a jagged array that has three items of an
array.
int[][] intJaggedArray = new int[3][];
 The following code snippet declares a jagged array that has two items of an
array.
string[][] stringJaggedArray = new string[2][];
Initializing Jagged Arrays
  Before a jagged array can be used, its items must be initialized. The
following code snippet initializes a jagged array; the first item with an array
of integers that has two integers, second item with an array of integers that
has 4 integers, and a third item with an array of integers that has 6 integers.
// Initializing jagged arrays
 intJaggedArray[0] = new int[2];
 intJaggedArray[1] = new int[4];
 intJaggedArray[2] = new int[6];
 We can also initialize a jagged array's items by providing the values of the
array's items. The following code snippet initializes item an array's items
directly during the declaration.
 // Initializing jagged arrays
 intJaggedArray[0] = new int[2]{2, 12};
 intJaggedArray[1] = new int[4]{4, 14, 24, 34};
 intJaggedArray[2] = new int[6] {6, 16, 26, 36, 46, 56 };
Accessing Jagged Arrays
  We can access a jagged array's items individually in the following way:
 Console.Write(intJaggedArray3[0][0]);
 Console.WriteLine(intJaggedArray3[2][5]);
  We can also loop through all of the items of a jagged array. The Length
property of an array helps a lot; it gives us the number of items in an array.
The following code snippet loops through all of the items of a jagged array
and displays them on the screen.
  // Loop through all items of a jagged array
 for (int i = 0; i < intJaggedArray3.Length; i++)
 {
     System.Console.Write("Element({0}): ", i);
     for (int j = 0; j < intJaggedArray3[i].Length; j++)
     {
         System.Console.Write("{0}{1}", intJaggedArray3[i][j], j ==
(intJaggedArray3[i].Length - 1) ? "" : " ");
     }
     System.Console.WriteLine();
 }
Array Class
 Array class is the mother of all arrays and provides functionality for creating,
manipulating, searching, and sorting arrays in .NET Framework.
  Array class, defined in the System namespace, is the base class for arrays in
C#. Array class is an abstract base class that means we cannot create an
instance of the Array class.
 Creating an Array
  Array class provides the CreateInstance method to construct an array. The
CreateInstance method takes first parameter as the type of items and second
and third parameters are the dimension and their range. Once an array is
created, we use SetValue method to add items to an array.
  The following code snippet creates an array and adds three items to the
array. As you can see the type of the array items is string and range is 3. You
will get an error message if you try to add 4thitem to the array.
 Array stringArray = Array.CreateInstance(typeof(String), 3);
 stringArray.SetValue("Mahesh Chand", 0);
 stringArray.SetValue("Raj Kumar", 1);
 stringArray.SetValue("Neel Beniwal", 2);
 Note: Calling SetValue on an existing item of an array overrides the previous
item value with the new value.
  The code snippet in Listing 2 creates a multi-dimensional array.
 Array intArray3D = Array.CreateInstance(typeof(Int32), 2, 3, 4);
 for (int i = intArray3D.GetLowerBound(0); i <= intArray3D.GetUpperBound(0);
i++)
     for (int j = intArray3D.GetLowerBound(1); j <=
intArray3D.GetUpperBound(1); j++)
         for (int k = intArray3D.GetLowerBound(2); k <=
intArray3D.GetUpperBound(2); k++)
         {
             intArray3D.SetValue((i * 100) + (j * 10) + k, i, j, k);
         }
  
 foreach (int ival in intArray3D)
 {
     Console.WriteLine(ival);
 }
The code snippet in Listing 3 creates an array and uses Array
properties to display property values.
  int[] intArray = new int[3] {0, 1, 2};
 if(intArray.IsFixedSize)
 {
     Console.WriteLine("Array is fixed size");
     Console.WriteLine("Size :" + intArray.Length.ToString());
     Console.WriteLine("Rank :" + intArray.Rank.ToString());
 }
Method or property Purpose
AsReadOnly() Public static method that returns a read-only instance
for a given array

BinarySearch() Overloaded public static method that searches a one-


dimensional sorted array

Clear() Public static method that sets a range of elements in the


array either to 0 or to a null reference

Clone() Public method that creates a deep copy of the current


array
ConstrainedCopy() Public static method that copies a section of one array
to another array; this method guarantees that the
destination array will be modified only if all specified
elements are copied successfully

ConvertAll() Public static method that converts an array of one type


into another type
Method or property Purpose
Copy() Overloaded public static method that copies a
section of one array to another array

CopyTo() Overloaded public method that copies all elements


in the current array to another

CreateInstance() Overloaded public static method that instantiates a


new instance of an array

Exists() Overloaded public static method that checks


whether an array contains elements that match a
condition

Find() Public static method that finds the first element


that matches a condition

FindAll() Public static method that finds all elements that


match a condition
FindIndex() Overloaded public static method that returns the
index of the first element that matches a condition
FindLast() Public static method that finds the last element that matches a condition

FindLastIndex() Overloaded public static method that returns the index of the last element
that matches a condition

ForEach() Public static method that performs an action on all elements of an array

GetEnumerator() Public method that returns an IEnumerator


Public method that returns the length of the specified dimension in the
GetLength()
array
GetLongLength() Public method that returns the length of the specified dimension in the
array as a 64-bit integer
GetLowerBound() Public method that returns the lower boundary of the specified
dimension of the array
GetUpperBound() Public method that returns the upper boundary of the specified
dimension of the array
GetValue() Overloaded public method that returns the value of an element of the
array
IndexOf() Overloaded public static method that returns the index (offset) of the first
instance of a value in a one-dimensional array
Initialize() Initializes all values in a value type array by calling the default constructor for each value; with
 
reference arrays, all elements in the array are set to null
IsFixedSize Required because Arrayimplements ICollection; with arrays, this will always return true (all arrays are
 
of a fixed size)
IsReadOnly Public property (required because Arrayimplements IList) that returns a Boolean value indicating
 
whether the array is read-only
IsSynchronized
Public property (required because Arrayimplements ICollection) that returns a Boolean value indicating
 
whether the array is thread-safe
LastIndexOf() Overloaded public static method that returns the index of the last instance of a value in a one-
 
dimensional array
Length Public property that returns the length of the array  

LongLength Public property that returns the length of the array as a 64-bit integer  

Initializes all values in a value type array by calling the default constructor for each value; with
Initialize() reference arrays, all elements in the array are set to null
IsFixedSize Required because Arrayimplements ICollection; with arrays, this will always return true (all arrays are of
a fixed size)
IsReadOnly Public property (required because Arrayimplements IList) that returns a Boolean value indicating
whether the array is read-only
IsSynchronized Public property (required because Arrayimplements ICollection) that returns a Boolean value indicating
whether the array is thread-safe
LastIndexOf() Overloaded public static method that returns the index of the last instance of a value in a one-
dimensional array
Length Public property that returns the length of the array
LongLength Public property that returns the length of the array as a 64-bit integer
Rank Public property that returns the number of dimensions of the array

Resize() Public static method that changes the size of an array

Reverse() Overloaded public static method that reverses the order of the
elements in a one-dimensional array

SetValue() Overloaded public method that sets the specified array elements to a
value

Sort() Overloaded public static method that sorts the values in a one-
dimensional array

SyncRoot Public property that returns an object that can be used to synchronize
access to the array

TrueForAll() Public static method that checks whether all elements match a
condition
Searching for an Item in an Array
 The BinarySearch static method of Array class can be used to search for an
item in an array.
 This method uses the binary search algorithm to search for an item.
 The method takes at least two parameters.
 First parameter is the array in which you would like to search and the second
parameter is an object that is the item you are looking for.
 If an item is found in the array, the method returns the index of that item
(based on first item as 0th item).
 Otherwise method returns a negative value. 
 Note: You must sort an array before searching. See comments in this article.
 Listing uses BinarySearch method to search an array for a string.  
 // Create an array and add 5 items to it
 Array stringArray = Array.CreateInstance(typeof(String), 5);
 stringArray.SetValue("Mahesh", 0);
 stringArray.SetValue("Raj", 1);
 stringArray.SetValue("Neel", 2);
 stringArray.SetValue("Beniwal", 3);
 stringArray.SetValue("Chand", 4);
  
 // Find an item
 object name = "Neel";
 int nameIndex = Array.BinarySearch(stringArray, name);
 if (nameIndex >= 0)
     Console.WriteLine("Item was at " + nameIndex.ToString() + "th position");
 else
     Console.WriteLine("Item not found");
Sorting Items in an Array
The Sort static method of the Array class can be used to sort array
items. This method has many overloaded forms. The simplest form
takes as a parameter the array you want to sort. Listing 5 uses the
Sort method to sort array items. Using the Sort method, you can
also sort a partial list of items.
 // Create an array and add 5 items to it
 Array stringArray = Array.CreateInstance(typeof(String), 5);
 stringArray.SetValue("Mahesh", 0);
 stringArray.SetValue("Raj", 1);
 stringArray.SetValue("Neel", 2);
 stringArray.SetValue("Beniwal", 3);
 stringArray.SetValue("Chand", 4);
 // Find an item
 object name = "Neel";
 int nameIndex = Array.BinarySearch(stringArray, name);
 if (nameIndex >= 0)
     Console.WriteLine("Item was at " + nameIndex.ToString() + "th position");
 else
     Console.WriteLine("Item not found");
 Console.WriteLine();
  Console.WriteLine("Original Array");
 Console.WriteLine("---------------------");
 foreach (string str in stringArray)
 {
     Console.WriteLine(str);
 }
  Console.WriteLine();
 Console.WriteLine("Sorted Array");
 Console.WriteLine("---------------------");
 Array.Sort(stringArray);
 foreach (string str in stringArray)
 {    Console.WriteLine(str);} 
 Although arrays in C# can be used just like arrays in many other
programming languages, they have one special attribute:
 They are implemented as objects.
 This fact is one reason that a discussion of arrays was deferred until objects
had been introduced.
 By implementing arrays as objects, several important advantages are gained,
not the least of which is that unused arrays can be garbage-collected.
One-Dimensional Arrays
 A one-dimensional array is a list of related variables. Such lists are common
in programming.
 For example, you might use a one-dimensional array to store the account
numbers of the active users on a network.
 Another array might store the current batting averages for a Cricket team.
 Because arrays in C# are implemented as objects, two steps are needed to
obtain an array for use in your program.
 First, you must declare a variable that can refer to an array.
 Second, you must create an instance of the array by use of new.
 Therefore, to declare a one dimensional array, you will typically use this
general form:
type[ ] array-name = new type[size];
 Here, type declares the element type of the array.
 The element type determines the data type of each element that comprises the
array. Notice the square brackets that follow type.
 They indicate that a one-dimensional array is being declared.
 The number of elements that the array will hold is determined by size.
If you come from a C or C++ background, pay special attention to
the way arrays are declared.
Specifically, the square brackets follow the type name, not the array
name.
 The following creates an int array of ten elements and links it to an array
reference variable named sample.
int[] sample = new int[10];
 The sample variable holds a reference to the memory allocated by new.
 This memory is large enough to hold ten elements of type int.
 As is the case when creating an instance of a class, it is possible to break the
preceding declaration in two. For example:
int[] sample;
sample = new int[10];
 In this case, when sample is first created, it refers to no physical object. It
is only after the second statement executes that sample refers to an array.
 An individual element within an array is accessed by use of an index.
 An index describes the position of an element within an array.
 In C#, all arrays have 0 as the index of their first element.
 Because sample has 10 elements, it has index values of 0 through 9. To
index an array, specify the number of the element you want, surrounded by
square brackets.
 Thus, the first element in sample is sample[0], and the last element is
sample[9].
 For example, the following program loads sample with the numbers 0
through 9:
// Demonstrate a one-dimensional array.
using System;
class ArrayDemo {
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]);
}
}
The output from the program is shown here:
sample[0]: 0
sample[1]: 1
sample[2]: 2
Conceptually, the sample array looks like this:
You declare a C# array with the following syntax:
type[] array-name;
For example:
int[] myIntArray;
You aren’t actually declaring an array.
Technically, you are declaring a variable (myIntArray) that will
hold a reference to an array of integers.
As always, we’ll use the shorthand and refer to myIntArray as the
array, knowing that we really mean a variable that holds a reference
to an (unnamed) array.
 The square brackets ([]) tell the C# compiler that you are declaring an array,
and the type specifies the type of the elements it will contain.
 In the previous example, myIntArray is an array of integers.
 You instantiate an array by using the new keyword.
 For example: myIntArray = new int[5];
 This declaration creates and initializes an array of five integers, all of which
are initialized to the value 0.
VB 6 programmers take note: in C#, the value of the size of the
array marks the number of elements in the array, not the upper
bound.
In fact, there is no way to set the upper or lower bound—with the
exception that you can set the lower bounds in multidimensional
arrays , but even that is not supported by the .NET Framework class
library.
Thus, the first element in an array is 0. The following C# statement
declares an array of 10 elements, with indexes 0 through 9:
string myArray[10];
The upper bound is 9, not 10, and you can’t change the size of the
array (i.e., there is no equivalent to the VB 6 Redim function).
arrays are objects and thus have properties.
One of the more useful of these is Length, which tells you how
many objects are in an array.
Array objects can be indexed from 0 to Length-1.
That is, if there are five elements in an array, their indexes are 0, 1,
2, 3, 4.
// Compute the average of a set of values.
using System;
class Average {
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); } }
 It is possible to initialize the contents of an array at the time it is instantiated
by providing a list of values delimited by curly brackets ({}).
 C# provides a longer and a shorter syntax:
int[] myIntArray = new int[5] { 2, 4, 6, 8, 10 }
int[] myIntArray = { 2, 4, 6, 8, 10 }
 There is no practical difference between these two statements, and most
programmers will use the shorter syntax, but see the note on syntaxes.
Both syntaxes exist because in some rare circumstances, you have
to use the longer syntax—specifically, if the C# compiler is unable
to infer the correct type for the array.
The params Keyword
 You can create a method that displays any number of integers to the console
by passing in an array of integers and then iterating over the array with a
foreach loop.
 The params keyword allows you to pass in a variable number of parameters
without necessarily explicitly creating the array.
 In the example, you create a method, DisplayVals( ), that takes a variable
number of integer arguments:
public void DisplayVals(params int[] intVals)
 The method itself can treat the array as though an integer array were
explicitly created and passed in as a parameter.
 You are free to iterate over the array as you would over any other array of
integers:
foreach (int i in intVals)
{
Console.WriteLine("DisplayVals {0}",i);
}
 The calling method, however, need not explicitly create an array: it can
simply pass in integers, and the compiler will assemble the parameters into
an array for the
 DisplayVals( ) method:
t.DisplayVals(5,6,7,8);
 You are free to pass in an array if you prefer:
int [] explicitArray = new int[5] {1,2,3,4,5};
t.DisplayVals(explicitArray);
Boundaries Are Enforced
 Array boundaries are strictly enforced in C#; it is a runtime error to overrun
or underrun the ends of an array.
Multidimensional Arrays
 You can think of an array as a long row of slots into which you can place
values.
 Once you have a picture of a row of slots, imagine 10 rows, one on top of
another.
 This is the classic two-dimensional array of rows and columns.
 The rows run across the array and the columns run up and down the array.
 A third dimension is possible, but somewhat harder to imagine.
 Make your arrays three-dimensional, with new rows stacked atop the old
two-dimensional array.
 C# supports two types of multidimensional arrays:
 rectangular
 In a rectangular array, every row is the same length.
 jagged
 A jagged array, however, is an array of arrays, each of which can be a different
length.
Rectangular arrays
 A rectangular array is an array of two (or more) dimensions.
 In the classic two dimensional array, the first dimension is the number of
rows and the second dimension is the number of columns.
 To declare a two-dimensional array, use the following syntax:
type [,] array-name
 For example, to declare and instantiate a two-dimensional rectangular array
named myRectangularArray that contains two rows and three columns of
integers, you would write:
int [,] myRectangularArray = new int[2,3];
 In this example, you declare a pair of constant values:
const int rows = 4;
const int columns = 3;
 that are then used to dimension the array:
int[,] rectangularArray = new int[rows, columns];
 The brackets in the int[,] declaration indicate that the type is an array of
integers, and the comma indicates that the array has two dimensions (two
commas would indicate three dimensions, etc.).
 The actual instantiation of rectangularArray with new int[rows, columns] sets the size
of each dimension.
 Here, the declaration and instantiation have been combined.
 Just as you can initialize a one-dimensional array using bracketed lists of
values, you can initialize a two-dimensional array using similar syntax.
 Example declares a two-dimensional array (rectangularArray), initializes its
elements using bracketed lists of values, and then prints the contents.
type[,] array_name = {
{ val, val, val, ..., val },
{ val, val, val, ..., val },
...
{ val, val, val, ..., val }
};
 Here, val indicates an initialization value. Each inner block designates a row.
 Within each row, the first value will be stored in the first position, the second
value in the second position, and so on.
 Notice that commas separate the initializer blocks and that a semicolon
follows the closing }.
 You imply the exact dimensions of the array by how you initialize it:
int[,] rectangularArrayrectangularArray = {
{0,1,2}, {3,4,5}, {6,7,8}, {9,10,11}
};
 Assigning values in four bracketed lists, each consisting of three elements,
implies a 4 × 3 array.
 Had you written this as:
int[,] rectangularArrayrectangularArray = {
{0,1,2,3}, {4,5,6,7}, {8,9,10,11}
};
 you would instead have implied a 3 × 4 array.
 You can see that the C# compiler understands the implications of your
clustering because it can access the objects with the appropriate offsets, as
illustrated in the output.
Jagged arrays
 A jagged array is an array of arrays.
 It is called “jagged” because each row need not be the same size as all the
others, and thus a graphical representation of the array would not be square.
 When you create a jagged array, you declare the number of rows in your
array.
 Each row will hold an array, which can be of any length. These arrays must
each be declared.
 You can then fill in the values for the elements in these “inner” arrays.
 A jagged array is an array of arrays in which the length of each array can
differ.
 Thus, a jagged array can be used to create a table in which the lengths of the
rows are not the same.
 In a jagged array, each dimension is a one-dimensional array.
 To declare a jagged array, use the following syntax, where the number of
brackets indicates the number of dimensions of the array:
type [] []...
 Jagged arrays are declared by using sets of square brackets to indicate each
dimension.
 For example, to declare a two-dimensional jagged array, you will use this
general form:
type[ ] [ ] array-name = new type[size][ ];
 Here, size indicates the number of rows in the array.
 The rows, themselves, have not been allocated. Instead, the rows are allocated
individually.
 This allows for the length of each row to vary.
 For example, the following code allocates memory for the first dimension of
jagged when it is declared.
 It then allocates the second dimensions manually.
int[][] jagged = new int[3][];
jagged[0] = new int[4];
jagged[1] = new int[3];
jagged[2] = new int[5];
 After this sequence executes, jagged looks like this:
const int rows = 4;
// declare the jagged array as 4 rows high
int[][] jaggedArray = new int[rows][];
// the first row has 5 elements
jaggedArray[0] = new int[5];
// a row with 2 elements
jaggedArray[1] = new int[2];
// a row with 3 elements
jaggedArray[2] = new int[3];
// the last row has 5 elements
jaggedArray[3] = new int[5];
 a jagged array is created with four rows:
int[][] jaggedArray = new int[rows][];
 Notice that the second dimension is not specified. This is set by creating a
new array for each row.
 Each array can have a different size:
// the first row has 5 elements
jaggedArray[0] = new int[5];
// a row with 2 elements
jaggedArray[1] = new int[2];
// a row with 3 elements
jaggedArray[2] = new int[3];
// the last row has 5 elements
jaggedArray[3] = new int[5];
 Once an array is specified for each row, you need only populate the various
members of each array and then print their contents to ensure that all went as
expected.
 Notice that when you access the members of a rectangular array, you put the
indexes all within one set of square brackets:
rectangularArrayrectangularArray[i,j]
 whereas with a jagged array you need a pair of brackets:
jaggedArray[3][i]
 You can keep this straight by thinking of the first array as a single array of
more than one dimension, and the jagged array as an array of arrays.
Assigning Array References
 As with other objects, when you assign one array reference variable to
another, you are simply making both variables refer to the same array.
 You are neither causing a copy of the array to be created, nor are you causing
the contents of one array to be copied to the other.
Using the Length Property
 A number of benefits result because C# implements arrays as objects. One
comes from the fact that each array has associated with it a Length property
that contains the number of elements that an array can hold.
 Thus, each array provides a means by which its length can be determined.
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();
Using Length with Jagged Arrays
 A special case occurs when Length is used with jagged arrays.
 In this situation, it is possible to obtain the length of each individual array.
class Jagged {
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();
The output is shown here:
Total number of network nodes: 4
CPU usage at node 0 CPU 0: 70%
CPU usage at node 0 CPU 1: 70%
CPU usage at node 0 CPU 2: 70%
CPU usage at node 1 CPU 0: 70%
CPU usage at node 1 CPU 1: 71%
CPU usage at node 1 CPU 2: 72%
CPU usage at node 1 CPU 3: 73%
CPU usage at node 1 CPU 4: 74%
CPU usage at node 1 CPU 5: 75%
CPU usage at node 1 CPU 6: 76%
CPU usage at node 2 CPU 0: 70%
CPU usage at node 2 CPU 1: 72%
CPU usage at node 3 CPU 0: 70%
CPU usage at node 3 CPU 1: 73%
CPU usage at node 3 CPU 2: 76%
CPU usage at node 3 CPU 3: 79%
CPU usage at node 3 CPU 4: 82%
 Pay special attention to the way Length is used on the jagged array
network_nodes.
 Recall, a two-dimensional jagged array is an array of arrays.
 Thus, when the expression
network_nodes.Length
 is used, it obtains the number of arrays stored in network_nodes, which is
four in this case.
 To obtain the length of any individual array in the jagged array, you will use
an expression such as this:
network_nodes[0].Length
 which, in this case, obtains the length of the first array.
Implicitly Typed Arrays
 The ability to declare implicitly typed variables by using the var keyword.
 These are variables whose type is determined by the compiler, based on the
type of the initializing expression.
 Thus, all implicitly typed variables must be initialized.
 Using the same mechanism, it is also possible to create an implicitly typed
array.
 An implicitly typed array is declared using the keyword var, but you do not
follow var with [ ].
 Furthermore, the array must be initialized because it is the type of the
initializers that determine the element type of the array.
 All of the initializers must be of the same or compatible type.
 Here is an example of an implicitly typed array:
var vals = new[] { 1, 2, 3, 4, 5 };
 This creates an array of int that is five elements long.
 A reference to that array is assigned to vals.
 Thus, the type of vals is “array of int” and it has five elements.
 Again, notice that var is not followed by [ ].
 Also, even though the array is being initialized, you must include new[ ].
 It’s not optional in this context.
 Here is another example. It creates a two-dimensional array of double:
var vals = new[,] { {1.1, 2.2}, {3.3, 4.4},{ 5.5, 6.6} };
 In this case, vals has the dimensions 2×3.
Indexers
 Sometimes you may need to access a collection within a class as though the
class itself were an array.
 For example, suppose you create a listbox control named myListBox that
contains a list of strings stored in a one-dimensional array, a private member
variable named myStrings.
 A listbox control contains member properties and methods in addition to its
array of strings.
 However, it would be convenient to be able to access the listbox array with
an index, just as though the listbox were an array.*
 For example, such a property would permit statements like the following:
string theFirstString = myListBox[0];
string theLastString = myListBox[Length-1];
 An indexer is a C# construct that allows you to access collections contained
by a class using the familiar [] syntax of arrays.
 An indexer is a special kind of property, and includes get and set accessors to
specify its behavior.
 You declare an indexer property within a class using the following syntax:
type this [type argument]{get; set;}
 The return type determines the type of object that will be returned by the
indexer, whereas the type argument specifies what kind of argument will be
used to index into the collection that contains the target objects.
 Although it is common to use integers as index values, you can index a
collection on other types as well, including strings.
 You can even provide an indexer with multiple parameters to create a
multidimensional array!
 The this keyword is a reference to the object in which the indexer appears.
 As with a normal property, you also must define get and set accessors, which
determine how the requested object is retrieved from or assigned to its
collection.
 C++ programmers take note: the indexer serves much the same purpose as
overloading the C++ index operator ([]).
 The index operator can’t be overloaded in C#, which provides the indexer in
its place.
 you can’t assign to an index that doesn’t have a value. So, if you write:
lbt[10] = "wow!";
 you will trigger the error handler in the set( ) method, which will note that the
index you’ve passed in (10) is larger than the counter (6).
 Of course, you can use the set( ) method for assignment; you simply have to
handle the indexes you receive.
 To do so, you might change the set( ) method to check the Length of the
buffer rather than the current value of counter.
 If a value was entered for an index that did not yet have a value, you would
update ctr:
set
{
// add only through the add method
if (index >= strings.Length )
{
// handle error
}
else
{
strings[index] = value;
if (ctr < index+1)
ctr = index+1;
}
}
 C# doesn’t require that you always use an integer value as the index to a
collection.
 When you create a custom collection class and create your indexer, you are
free to create indexers that index on strings and other types.
 In fact, the index value can be overloaded so that a given collection can be
indexed, for example, by an integer value or by a string value, depending on
the needs of the client.
 In the case of your listbox, you might want to be able to index into the listbox
based on a string.
 The indexer calls findString( ), which is a helper method that returns a record
based on the value of the string provided.
 The careful reader will note that if the string doesn’t match, a value of -1 is
returned, which is then used as an index into myStrings.
 This action then generates an exception (System.NullReferenceException),
 as you can see by uncommenting the following line in Main( ): lbt["xyz"] =
"oops";
 The proper handling of not finding a string is, as they say, left as an exercise
for the reader.
 You might consider displaying an error message or otherwise allowing the
user to recover from the error.
public ListBoxTest(params string[] initialStrings)
{
// allocate space for the strings
strings = new String[256];
// copy the strings passed in to the constructor
foreach (string s in initialStrings)
{
strings[ctr++] = s;
}
}
 the listbox maintains a simple array of strings: strings.
 Again, in a real listbox, you might use a more complex and dynamic
container, such as a hash table.
 The member variable ctr will keep track of how many strings have been
added to this array.
 Initialize the array in the constructor with the statement:
strings = new String[256];
 The remainder of the constructor adds the parameters to the array.
 Again, for simplicity, you add new strings to the array in the order received.
 Because you can’t know how many strings will be added, you use the
keyword params.
public void Add(string theString)
{
if (ctr >= strings.Length)
{
// handle bad index
}
else
strings[ctr++] = theString;
}
// allow array-like access
public string this[int index]
{
get
{
if (index < 0 || index >= strings.Length)
{
// handle bad index
}
return strings[index];
}
 The Add( ) method of ListBoxTest does nothing more than append a new
string to the internal array.
 The key method of ListBoxTest, however, is the indexer.
 An indexer is unnamed, so use the this keyword:
public string this[int index]
 The syntax of the indexer is very similar to that for properties.
 There is either a get( ) method, a set( ) method, or both.
 In the case shown, the get( ) method endeavors to implement rudimentary
bounds-checking, and assuming the index requested is acceptable, it returns
the value requested
set
{
// add only through the add method
if (index >= ctr)
{
// handle error
}
else
strings[index] = value;
}
}
// publish how many strings you hold
public int GetNumEntries( )
{
return ctr;
}
}
 The set( ) method checks to make sure that the index you are setting already
has a value in the listbox.
 If not, it treats the set as an error. (New elements can only be added using
Add with this approach.)
 The set accessor takes advantage of the implicit parameter value that
represents whatever is assigned using the index operator.
 Thus, if you write:
lbt[5] = "Hello World"
 the compiler will call the indexer set( ) method on your object and pass in the
string Hello World as an implicit parameter named value.
Strings
 Strings in C# are objects and derive from System.String, alias string.
 Each string is an immutable sequence of zero or more characters.
 Any attempt, therefore, to change a string via one of its methods creates an
entirely new string object.
 A string is often initialized to a string literal, a sequence of zero or more
characters enclosed in double quotes, such as "Csharp".
 A string is also zero-based.
 Hence, the first character of a string is designated at index 0.
 Each manipulation of an immutable string created by System.String results in a
new string object being allocated on the heap.
 Many of these immutable strings will be unreachable and eventually garbage
collected. For example:
1 string myName = "Michel";
2
3 myName = String.Concat(myName, " de");
4 myName = String.Concat(myName, " Champlain");
 The above concatenation has instantiated five strings:
 three for the literal strings ("Michel", " de", and " Champlain"),
 one as the result of the concatenation on line 3 ("Michel de"),
 and another as the last concatenation on line 4 ("Michel de Champlain").
 Repeating concatenations or making intensive manipulations on immutable
strings within loops may be very inefficient.
 To improve performance, the StringBuilder class in the Tip namespace
System.Text is a better choice.
 It represents instead mutable strings that are allocated only once on the heap.
 An object of the StringBuilder class allows a string of up to 16 characters by
default and grows dynamically as more characters are added.
 Its maximum size may be unbounded or increased to a configurable
maximum.
 This example shows the equivalent concatenation of strings using the
Append method:
 StringBuilder myName = new StringBuilder("Michel");
 myName.Append(" de");
 myName.Append(" Champlain");
 The three literal strings are still allocated, but only one StringBuilder object
assigned to myName is allocated and reused.
 In addition to methods such as Insert, Remove, and Replace, the
StringBuilder class is equipped with a number of overloaded constructors:
DateTime
 Time representations are complicated.
 The C# language provides the DateTime type.
 This type can be used to get the current time and relative times such as
yesterday, tomorrow and certain days in years.
 DateTime offers many useful methods and properties for date and time
computations.
Constructor
 For the DateTime type in the C# language and .NET Framework, you can use
the instance constructor with the new operator to instantiate a new DateTime
instance.
 The arguments to the constructor must match a real date that occurred.
 This example also shows how you can write a DateTime to the console.
 It also compares a DateTime against the Today value. Console.WriteLine
using System;
class Program
{
static void Main()
{
// This DateTime is constructed with an instance constructor.
// ... We write it to the console.
// ... If this is today, the second line will be "True".
DateTime value = new DateTime(2010, 1, 18);
Console.WriteLine(value);
Console.WriteLine(value == DateTime.Today);
}
}
Find yesterday
 Here we see how to subtract one day from the current day.
 We do this by adding -1 to the current day.
 This is necessary because no "Subtract Days" method is provided.
 An extension method could help depending on your style.
using System;
class Program
{
static void Main()
{
Console.WriteLine("Today: {0}", DateTime.Today);
DateTime y = GetYesterday();
Console.WriteLine("Yesterday: {0}", y);
}
/// <summary>
/// Gets the previous day to the current day.
/// </summary>
static DateTime GetYesterday()
{
// Add -1 to now
return DateTime.Today.AddDays(-1);
}
}
Today: 11/30/2008 12:00:00 AM
Yesterday: 11/29/2008 12:00:00 AM
 The example displays the current day.
 Note that the Console.WriteLine implicitly converts the DateTime.Today
argument using its ToString method.
 This would make them reusable across projects.
 Here we see how you can add one using the DateTime Add method to figure
out tomorrow.
 This is useful for using date queries in databases, as you usually have to
select a range of dates.
using System;
class Program
{
static void Main()
{
Console.WriteLine("Today: {0}", DateTime.Today);
DateTime d = GetTomorrow();
Console.WriteLine("Tomorrow: {0}", d);
}
/// <summary>
/// Gets the next day, tomorrow.
/// </summary>
static DateTime GetTomorrow()
{
return DateTime.Today.AddDays(1);
}
}
Output
Today: 11/30/2008 12:00:00 AM
Tomorrow: 12/1/2008 12:00:00 AM
 This method and the previous ones are static methods because they do not
require state to be saved.
 DateTime.Today is not an instance of the class.
 DateTime.Add uses offsets, meaning it accepts both negative and positive
numbers. Here we go back in time.
Name Description

Add Returns a new DateTime that adds the value of the specified 


TimeSpan to the value of this instance.

Returns a new DateTime that adds the specified number of days to


AddDays the value of this instance.

Returns a new DateTime that adds the specified number of hours


AddHours to the value of this instance.

Returns a new DateTime that adds the specified number of


AddMilliseconds milliseconds to the value of this instance.

Returns a new DateTime that adds the specified number of


AddMinutes minutes to the value of this instance.

Returns a new DateTime that adds the specified number of months


AddMonths to the value of this instance.

Returns a new DateTime that adds the specified number of


AddSeconds seconds to the value of this instance.

Returns a new DateTime that adds the specified number of ticks to


AddTicks the value of this instance.
Name Description
Returns a new DateTime that adds the specified number of years to the value of
AddYears this instance.

Compares two instances of DateTime and returns an integer that indicates


Compare whether the first instance is earlier than, the same as, or later than the second
instance.

Compares the value of this instance to a specified DateTime value and returns an


CompareTo(DateTime) integer that indicates whether this instance is earlier than, the same as, or later
than the specified DateTime value.

Compares the value of this instance to a specified object that contains a specified 
CompareTo(Object) DateTime value, and returns an integer that indicates whether this instance is
earlier than, the same as, or later than the specified DateTime value.

Returns the number of days in the specified month and year.


DaysInMonth

Returns a value indicating whether the value of this instance is equal to the value
Equals(DateTime) of the specifiedDateTime instance.

Returns a value indicating whether this instance is equal to a specified


Equals(Object) object. (OverridesValueType.Equals(Object).)

Returns a value indicating whether two DateTime instances have the same date


Equals(DateTime, DateTi and time value.
me)
Name Description
Converts the value of this instance to all the string representations supported by
GetDateTimeFormats the standard date and time format specifiers.

Converts the value of this instance to all the string representations supported by
GetDateTimeFormats(Ch the specified standard date and time format specifier.
ar)
Converts the value of this instance to all the string representations supported by
GetDateTimeFormats(IF the standard date and time format specifiers and the specified culture-specific
ormatProvider) formatting information.

Converts the value of this instance to all the string representations supported by
GetDateTimeFormats(Ch the specified standard date and time format specifier and culture-specific
ar, IFormatProvider) formatting information.

Gets the Type of the current instance. (Inherited from Object.)


GetType

Returns the TypeCode for value type DateTime.


GetTypeCode

Subtracts the specified date and time from this instance.


Subtract(DateTime)

Returns an indication whether the specified year is a leap year.


IsLeapYear
The Root of All Types: Object
 All C# classes, of any type, are treated as though they ultimately derive from
System.Object.
 Interestingly, this includes value types.
 A base class is the immediate “parent” of a derived class.
 A derived class can be the base to further derived classes, creating an
inheritance “tree” or hierarchy.
 A root class is the topmost class in an inheritance hierarchy.
 In C#, the root class is Object.
 The nomenclature is a bit confusing until you imagine an upside-down tree,
with the root on top, and the derived classes below.
 Thus, the base class is considered to be “above” the derived class.
 C++ programmers take note: C# uses single inheritance with a monolithic
class hierarchy: every class inherits from a base class of Object, and multiple
inheritance is not possible.
 However, C# interfaces provide many of the benefits of multiple inheritance.
 Object provides a number of virtual methods that subclasses can and do
override.
 These include Equals( ) to determine whether two objects are the same;
GetType( ), which returns the type of the object; and ToString( ), which
returns a string to represent the current object
 summarizes the methods of Object.
 All the built-in types, such as int, derive from Object and so can invoke
Object’s methods.
 The Write and WriteLine methods of Console will automatically invoke the
ToString( ) method on any object provided.
 The default behaviour console.writeLine is to return a string with the name
of the class itself.
 Classes don’t need to explicitly declare that they derive from Object; the
inheritance is implicit.
Nesting Classes
 Classes have members, and it is entirely possible for the member of a class to
be another user-defined type.
 Thus, a Button class might have a member of type Location, and a Location
class might contain members of type Point.
 Finally, Point might contain members of type int.
 At times, the contained class might exist only to serve the outer class, and
there might be no reason for it to be otherwise visible. (In short, the
contained class acts as a helper class.)
 You can define the helper class within the definition of the outer class.
 The contained, inner class is called a nested class, and the class that contains
it is called, simply, the outer class.
 Nested classes have the advantage of access to all the members of the outer
class.
 A method of a nested class can access private members of the outer class.
 In addition, the nested class can be hidden from all other classes—that is, it
can be private to the outer class.
 Finally, a nested class that is public is accessed within the scope of the outer
class.
 If Outer is the outer class, and Nested is the (public) inner class, refer to Nested
as Outer.Nested, with the outer class acting (more or less) as a namespace or
scope.
 Java programmers take note: nested classes are roughly equivalent to static
inner classes; there is no C# equivalent to Java’s nonstatic inner classes.
 The nested class is shown in bold.
 The FractionArtist class provides only a single member, the Draw( ) method.
 What is particularly interesting is that Draw( ) has access to the private data
members f.numerator and f.denominator, to which it wouldn’t have had
access if it weren’t a nested class.
 Notice in Main( ) that to declare an instance of this nested class, you must
specify the type name of the outer class:
 Fraction.FractionArtist fa = new Fraction.FractionArtist( );
 FractionArtist is scoped to be within the Fraction class.
Specialization and Generalization
 Classes and their instances (objects) do not exist in a vacuum, but rather in a
network of interdependencies and relationships, just as we, as social animals,
live in a world of relationships and categories.
 One of the most important relationships among objects in the real world is
specialization, which can be described as the is-a relationship.
 When we say that a dog is a mammal, we mean that the dog is a specialized
kind of mammal.
 It has all the characteristics of any mammal (it bears live young, nurses with
milk, has hair), but it specializes these characteristics to the familiar
characteristics of canis domesticus.
 A cat is also a mammal.
 As such, we expect it to share certain characteristics with the dog that are
generalized in Mammal, but to differ in those characteristics that are
specialized in cats.
 The specialization and generalization relationships are both reciprocal and
hierarchical.
 Specialization is just the other side of the generalization coin:
 Mammal generalizes what is common between dogs and cats, and dogs and
cats specialize mammals to their own specific subtypes.
 These relationships are hierarchical because they create a relationship tree,
with specialized types branching off from more generalized types.
 As you move "up" the hierarchy, you achieve greater generalization.
 You move up toward Mammal to generalize that dogs, cats, and horses all
bear live young.
 As you move "down" the hierarchy you specialize.
 Thus, the cat specializes Mammal in having claws (a characteristic) and
purring (a behavior).
 Similarly, when you say that ListBox and Button are Windows, you indicate
that there are characteristics and behaviors of Windows that you expect to
find in both of these types.
 In other words, Window generalizes the shared characteristics of
both ListBox and Button, while each specializes its own particular
characteristics and behaviors.
 The Unified Modeling Language (UML) is a standardized language for
describing an object-oriented system.
 The UML has many different visual representations, but in this case, all you
need to know is that classes are represented as boxes.
 The name of the class appears at the top of the box, and (optionally) methods
and members can be listed in the sections within the box.
 In the UML, you model specialization relationships.
 Note that the arrow points from the more specialized class up to the more
general class.
 In the figure, the more specialized Button and ListBox classes point up to the
more general Window class.
 It is not uncommon for two classes to share functionality.
 When this occurs, you can factor out these commonalities into a shared base
class, which is more general than the specialized classes.
 This provides you with greater reuse of common code and gives you code that
is easier to maintain, because the changes are located in a single class rather
than scattered among numerous classes.
 For example, suppose you started out creating a series of objects, as
illustrated in Figure.
 After working with RadioButtons, CheckBoxes, and Command buttons for a
while, you realize that they share certain characteristics and behaviors that
are more specialized than Window, but more general than any of the three.
 You might factor these common traits and behaviors into a common base
class, Button, and rearrange your inheritance hierarchy, as shown in Figure.
 This is an example of how generalization is used in object-oriented
development.
 The UML diagram in Figure depicts the relationship among the factored
classes and shows that both ListBox and Button derive from Window, and
that Button is specialized into CheckBoxand Command.
 Finally, RadioButton derives from CheckBox.
 You can thus say that RadioButton is a CheckBox, which in turn is a Button,
and that Buttons are Windows.
 This is not the only, or even necessarily the best, organization for these
objects, but it is a reasonable starting point for understanding how these types
(classes) relate to one another.
 In C#, the specialization relationship is implemented using a principle
called inheritance.
 This is not the only way to implement specialization, but it is the most
common and most natural way to implement this relationship.
 Saying that ListBox inherits from (or derives from) Window indicates that it
specializes Window. 
 Window is referred to as the base class, and ListBox is referred to as
the derived class.
 That is, ListBox derives its characteristics and behaviors from Window and
then specializes to its own particular needs.
 You’ll often see the immediate base class referred to as the parent class, and
the derived class referred to as the child class, while the topmost
class, Object, is called the root class.
 In C#, you create a derived class by adding a colon after the name of the
derived class, followed by the name of the base class:
public class ListBox : Window
 This code declares a new class, ListBox, that derives from Window.
 You can read the colon as "derives from."
 The derived class inherits all the members of the base class (both member
variables and methods), and methods of the derived class have access to all
the public and protected members of the base class.
 The derived class is free to implement its own version of a base class
method.
 This is called hiding the base class method and is accomplished by marking
the method with the keyword new.
 (Many C# programmers advise never hiding base class methods as it is
unreliable, hard to maintain, and confusing.)
 The new class ListBox derives from Window and has its own constructor,
which takes three parameters.
 The ListBox constructor invokes the constructor of its parent by placing a
colon (:) after the parameter list and then invoking the base class constructor
with the keyword base:
public ListBox( int theTop, int theLeft, string theContents):
base(theTop, theLeft) // call base constructor
 Because classes cannot inherit constructors, a derived class must implement
its own constructor and can only make use of the constructor of its base class
by calling it explicitly.
 If the base class has an accessible default constructor, the derived constructor
is not required to invoke the base constructor explicitly; instead, the default
constructor is called implicitly as the object is constructed.
 However, if the base class does not have a default constructor, every derived
constructor must explicitly invoke one of the base class constructors using
the base keyword.
 The keyword base identifies the base class for the current object.
  if you do not declare a constructor of any kind, the compiler creates a default
constructor for you.
 Whether you write it yourself or you use the one provided by the compiler, a
default constructor is one that takes no parameters.
 Note, however, that once you do create a constructor of any kind (with or
without parameters), the compiler does not create a default constructor for
you.
Controlling Access
 You can restrict the visibility of a class and its members through the use of
access modifiers, such as public, private, and protected.
 As you’ve seen, public allows a member to be accessed by the member
methods of other classes, while privateindicates that the member is visible
only to member methods of its own class.
 The protected keyword extends visibility to methods of derived classes.
 Classes, as well as their members, can be designated with any of these
accessibility levels.
 If a class member has a different access designation than the class, the more
restricted access applies.
 Thus, if you define a class, myClass, as follows:
public class MyClass
{
// ... protected int myValue;
}
 The accessibility for myValue is protected even though the class itself is
public.
 A public class is one that is visible to any other class that wishes to interact
with it.
 If you create a new class, myOtherClass, that derives from myClass, like this:
public class MyClass : MyOtherClass
{
Console.WriteLine("myInt: {0}", myInt);
}
 MyOtherClass can access myInt, because MyOtherClass derives
from MyClass, and myInt is protected.
 Any class that doesn’t derive fromMyClass would not be able to
access myInt.
 It is more common to make properties and methods protected than it is to
make member variables protected.
 Member variables are almost always private.
Polymorphism
 There are two powerful aspects to inheritance.
 One is code reuse.
 When you create a ListBox class, you’re able to reuse some of the logic in
the base (Window) class.
 What is arguably more powerful, however, is the second aspect of
inheritance: 
 polymorphism. 
 Poly means many and morphmeans form.
 Thus, polymorphism refers to being able to use many forms of a type without
regard to the details.
 When the phone company sends your phone a ring signal, it does not know
what type of phone is on the other end of the line.
 You might have an old-fashioned Western Electric phone that energizes a
motor to ring a bell, or you might have an electronic phone that plays digital
music.
 As far as the phone company is concerned, it knows only about the "base
type" phone and expects that any “derived” instance of this type knows how
to ring.
 When the phone company tells your phone to ring, it, effectively, calls your
phone’s ring method, and old fashioned phones ring, digital phones trill, and
cutting-edge phones announce your name.
 The phone company doesn’t know or care what your individual phone does;
it treats your telephone polymorphically.
 Because a ListBox is a Window and a Button is a Window, you expect to be
able to use either of these types in situations that call for a Window.
 For example, a form might want to keep a collection of all the derived
instances of Window it manages (buttons, lists, and so on), so that when the
form is opened, it can tell each of its Windows to draw itself.
 For this operation, the form does not want to know which elements
are ListBoxes and which are Buttons;
 it just wants to tick through its collection and tell each one to “draw.”
 In short, the form wants to treat all its Window objects polymorphically.
 You implement polymorphism in two steps:
1. Create a base class with virtual methods.
2. Create derived classes that override the behavior of the base class’s virtual
methods.
 To create a method in a base class that supports polymorphism, mark the
method as virtual.
 For example, to indicate that the method DrawWindow( ) of class Window in
is polymorphic, add the keyword virtual to its declaration, as follows:
public virtual void DrawWindow( )
 Each derived class is free to inherit and use the base class’s DrawWindow( )
method as is or to implement its own version of DrawWindow( ).
 If a derived class does override the DrawWindow( ) method, that overridden
version will be invoked for each instance of the derived class.
 You override the base class virtual method by using the keyword override in
the derived class method definition, and then add the modified code for that
overridden method.
 The runtime type of an object is the actual (derived) type.
 At compile time, you do not have to decide what kind of objects will be
added to your collection, so long as they all derive from the declared type (in
this case, Window).
 At runtime, the actual type is discovered and the right method is called. This
allows you to pick the actual type of objects to add to the collection while the
program is running.
public override void DrawWindow( )
{
base.DrawWindow( ); // invoke the base method
Console.WriteLine ("Writing string to the listbox: {0}", listBoxContents);
}
 The keyword override tells the compiler that this class has intentionally
overridden how DrawWindow( ) works.
 Similarly, you’ll override DrawWindow( ) in another class that derives from
Window: the Button class.
 In the body of the example, you create three objects: a Window, a ListBox,
and a Button.
 Then you call DrawWindow( ) on each:
Window win = new Window(1,2);
ListBox lb = new ListBox(3,4,"Stand alone list box");
Button b = new Button(5,6);
win.DrawWindow( );
lb.DrawWindow( );
b.DrawWindow( );
 This works much as you might expect.
 The correct DrawWindow( ) method is called for each.
 So far, nothing polymorphic has been done (after all, you called the Button
version of DrawWindow on a Button object).
 The real magic starts when you create an array of Window objects.
 Because a ListBox is a Window, you are free to place a ListBox into an array
of Windows.
 Similarly, you can add a Button to a collection of Windows, because
a Button is a Window.
Window[] winArray = new Window[3];
winArray[0] = new Window(1,2);
winArray[1] = new ListBox(3,4,"List box in array");
winArray[2] = new Button(5,6);
 The first line of code declares an array named winArray that will hold
three Window objects.
 The next three lines add new Window objects to the array. The first adds an
object of type Window.
 The second adds an object of type ListBox (which is a Window because
ListBox derives from Window), and the third adds an object of type Button,
which is also a type of Window.
 What happens when you call DrawWindow( ) on each of these objects?
for (int i = 0; i < winArray.Length-1; i++)
{
winArray[i].DrawWindow();
}
 This code uses i as a counter variable.
 It calls DrawWindow( ) on each element in the array in turn.
 The value i is evaluated each time through the loop, and that value is used as
an index into the array.
 All the compiler knows is that it has three Window objects and that you’ve
called DrawWindow( ) on each.
 If you had not marked DrawWindow( ) as virtual, Window’s original
DrawWindow( ) method would be called three times.
 However, because you did mark DrawWindow( ) as virtual, and because the
derived classes override that method, when you call DrawWindow( ) on the
array, the right thing happens for each object in the array.
 Specifically, the compiler determines the runtime type of the actual objects
(a Window, aListBox, and a Button) and calls the right method on each. This
is the essence of polymorphism.
 The runtime type of an object is the actual (derived) type.
 At compile time, you do not have to decide what kind of objects will be
added to your collection, so long as they all derive from the declared type (in
this case, Window).
 At runtime, the actual type is discovered and the right method is called.
 This allows you to pick the actual type of objects to add to the collection
while the program is running.
Abstract classes
 Abstract classes, marked by the keyword abstract in the class definition, are
typically used to define a base class in the hierarchy.
 What's special about them, is that you can't create an instance of them - if
you try, you will get a compile error.
 Instead, you have to subclass them, and create an instance of your subclass.
 So when do you need an abstract class?
 It really depends on what you do.
 To be honest, you can go a long way without needing an abstract class, but
they are great for specific things, like frameworks, which is why you will
find quite a bit of abstract classes within the .NET framework it self.
 A good rule of thumb is that the name actually makes really good sense -
abstract classes are very often, if not always, used to describe something
abstract, something that is more of a concept than a real thing. 
 Abstract classes are one of the essential behaviors provided by .NET.
 Commonly, you would like to make classes that only represent base classes,
and don’t want anyone to create objects of these class types.
 You can make use of abstract classes to implement such functionality in C#
using the modifier 'abstract'.
 An abstract class means that, no object of this class can be instantiated, but
can make derivations of this.
 An example of an abstract class declaration is:
 abstract class absClass
{
}
 An abstract class can contain either abstract methods or non abstract
methods.
 Abstract members do not have any implementation in the abstract class, but
the same has to be provided in its derived class.
 An example of an abstract method:
abstract class absClass
{
public abstract void abstractMethod();
}
 Also, note that an abstract class does not mean that it should contain abstract
members.
 Even we can have an abstract class only with non abstract members.
 For example:
abstract class absClass
{
public void NonAbstractMethod()
{
Console.WriteLine("NonAbstract Method");
}
}
Important rules applied to abstract classes
 An abstract class cannot be a sealed class. I.e. the following declaration is
incorrect.
//Incorrect
abstract sealed class absClass
{
}
 Declaration of abstract methods are only allowed in abstract classes.
 An abstract method cannot be private.
 //Incorrect
private abstract int MultiplyTwoNumbers();
 The access modifier of the abstract method should be same in both the
abstract class and its derived class.
 If you declare an abstract method as protected, it should be protected in its
derived class.
 Otherwise, the compiler will raise an error.
 An abstract method cannot have the modifier virtual. Because an abstract
method is implicitly virtual.
 //Incorrect
 public abstract virtual int MultiplyTwoNumbers();
 An abstract member cannot be static.
 //Incorrect
 publpublic abstract static int MultiplyTwoNumbers();
Abstract class vs. Interface
 An abstract class can have abstract members as well non abstract members.
 But in an interface all the members are implicitly abstract and all the
members of the interface must override to its derived class.
 An example of interface:
 interface iSampleInterface
{
 //All methods are automaticall abstract
 int AddNumbers(int Num1, int Num2);
 int MultiplyNumbers(int Num1, int Num2);
}
 Defining an abstract class with abstract members has the same effect to
defining an interface.
 The members of the interface are public with no implementation.
 Abstract classes can have protected parts, static methods, etc.
 A class can inherit one or more interfaces, but only one abstract class.
 Abstract classes can add more functionality without destroying the child
classes that were using the old version.
 In an interface, creation of additional functions will have an effect on its
child classes, due to the necessary implementation of interface methods to
classes.
 The selection of interface or abstract class depends on the need and design of
your project.
 You can make an abstract class, interface or combination of both depending
on your needs.
Abstract Class
 An Abstract class is an incomplete class or special class we can't instantiate.
 We can use an Abstract class as a Base Class.
 An Abstract method must be implemented in the non-Abstract class using the
override keyword.
 After overriding the abstract method is in the non-Abstract class.
 We can derive this class in another class and again we can override the same
abstract method with it. 
Features:
 An abstract calss can inherit from a class and one or more interfaces.
 An abstract class can implement code with non-Abstract methods.
 An Abstract class can have modifiers for methods, properties etc.
 An Abstract class can have constants and fields.
 An abstract class can implement a property.
 An abstract class can have constructors or destructors.
 An abstract class cannot be inherited from by structures.
 An abstract class cannot support multiple inheritance.
 Abstract methods have no implementations.
 The implementation logic is provided rather by classes that derive from them.
 We use an abstract class to create a base template for derived classes.
 Certain restrictions, negatives and positives are found in abstract types.

You might also like