Using Indexers and Properties


Although the preceding examples have demonstrated the basic mechanism of indexers and properties, they haven’t displayed their full power. To conclude this chapter, a class called RangeArray is developed that uses indexers and properties to create an array type in which the index range of the array is determined by the programmer.

As you know, in C# all arrays begin indexing at zero. However, some applications would benefit from an array that allows indexes to begin at any arbitrary point. For example, in some situations it might be more convenient for an array to begin indexing with 1. In another situation it might be beneficial to allow negative indices, such as an array that runs from 5 to 5. The RangeArray class developed here allows these and other types of indexing.

Using RangeArray, you can write code like this:

 RangeArray ra = new RangeArray(-5, 10); // array with indexes from -5 to 10 for(int i=-5; i <= 10; i++) ra[i] = i; // index from -5 to 10

As you can guess, the first line constructs a RangeArray that runs from 5 to 10, inclusive. The first argument specifies the beginning index. The second argument specifies the ending index. Once ra has been constructed, it can be indexed from 5 to 10.

The entire RangeArray class is shown here, along with RangeArrayDemo, which demonstrates the array. As implemented here, RangeArray supports arrays of int, but you can change the type of data to any other.

 /* 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 boundaries.   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");   } }

The output from the program is shown here:

 Length of ra: 11 Contents of ra: -5 -4 -3 -2 -1 0 1 2 3 4 5 Length of ra2: 10 Contents of ra2: 1 2 3 4 5 6 7 8 9 10 Length of ra3: 9 Contents of ra3: -20 -19 -18 -17 -16 -15 -14 -13 -12

As the output verifies, objects of type RangeArray can be indexed in ways other than starting at zero. Let’s look more closely at how RangeArray is implemented.

RangeArray begins by defining the following private instance variables:

 // 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

The underlying array is referred to by a. This array is allocated by the RangeArray constructor. The index of the lower bound of the array is stored in lowerBound, and the index of the upper bound is stored in upperBound. Next, the instance variables that support the Length and Error properties are declared.

The RangeArray constructor is shown here:

 // Construct array given its boundaries. 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; }

A RangeArray is constructed by passing the lower bound index in low and the upper bound index in high. The value of high is then incremented because the indices specified are inclusive. Next, a check is made to ensure that the upper index is greater than the lower index. If not, an error is reported and a one-element array is created. Next, storage for the array is allocated and assigned to a. Then len (which underlies the Length property) is set equal to the number of elements in the array. Finally, lowerBound and upperBound are set.

RangeArray then implements the Length and Error properties, as shown here:

 // Read-only Length property. public int Length {   get {     return len;   } } // Read-only Error property. public bool Error {   get {     return errflag;   } }

These properties are similar to those used by the FailSoftArray and work in the same way.

Next, RangeArray implements its indexer, as shown here:

 // 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;   } }

This indexer is similar to the one used by FailSoftArray with one important exception. Notice the expression that indexes a. It is

 index - lowerBound

This expression transforms the index passed in index into a zero-based index suitable foruse on a. This expression works whether lowerBound is positive, negative, or zero.

The ok( ) method is shown here:

 // Return true if index is within bounds. private bool ok(int index) {   if(index >= lowerBound & index <= upperBound) return true;   return false; }

It is similar to the one used by FailSoftArray except that the range is checked by testing it against the values in lowerBound and upperBound.

RangeArray illustrates just one kind of custom array that you can create through the use of indexers and properties. There are, of course, several others. For example, you can create dynamic arrays, which expand and contract as needed, associative arrays, and sparse arrays. You might want to try creating one of these types of arrays as an exercise.




C# 2.0(c) The Complete Reference
C# 2.0: The Complete Reference (Complete Reference Series)
ISBN: 0072262095
EAN: 2147483647
Year: 2006
Pages: 300

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net