Indexers Are Also Inherited and Can Be Overridden


Even though Chapter 14, "Class Anatomy III: Writing Intuitive Code," told us that indexers do not carry a name, like its method and property siblings, but instead are called by referring to an object name followed by a pair of square brackets enclosing an indexer, they are still inherited and can be overridden like methods and properties. Listing 16.5 demonstrates how an indexer can be overridden and also introduces a new use for the base keyword (other than when used as part of the constructor initializer discussed earlier), which allows you to call the indexer of a base class.

Listing 16.5 SeasonalAdjustment.cs
01: using System; 02: 03: class ProductionList 04: { 05:     private uint[] production = new uint[4]; 06: 07:     public virtual uint this [uint index] 08:     { 09:         get 10:         { 11:             return production[index]; 12:         } 13: 14:         set 15:         { 16:             production[index] = value; 17:         } 18:     } 19: } 20: 21: class ProductionSeasonAdjust : ProductionList 22: { 23:     public override uint this [uint index] 24:     { 25:         get 26:         { 27:             if(index < 2) 28:                return base[index] + 50; 29:             else 30:                 return base[index] - 30; 31:         } 32: 33:         set 34:         { 35:             base[index] = value; 36:         } 37:     } 38:  39:     public uint TotalSeasonalAdjusted 40:     { 41:         get 42:         { 43:             uint tempTotal = 0; 44: 45:             for(uint i = 0; i < 4; i++) 46:             { 47:                 tempTotal += this[i]; 48:             } 49:             return tempTotal; 50:         } 51:     } 52: } 53: 54: class Tester 55: { 56:     public static void Main() 57:     { 58:         ProductionSeasonAdjust prodAdjust = new ProductionSeasonAdjust(); 59: 60:         prodAdjust[0] = 100; 61:         prodAdjust[1] = 300; 62:         prodAdjust[2] = 200; 63:         prodAdjust[3] = 500; 64:         Console.WriteLine("Production in first quarter season adjusted: " + 65:             prodAdjust[0]); 66:         Console.WriteLine("Total production seasonally adjusted: " + 67:             prodAdjust.TotalSeasonalAdjusted); 68:     } 69: } Production in first quarter season adjusted: 150 Total production seasonally adjusted: 1140 

The ProductionList class (lines 3 19) is meant to hold quarterly industrial production figures from part of the economy in a country. The class represents the production array declared in line 5, so an indexer is implemented in lines 7 18 to provide convenient access to this array. Notice that line 7 declares the indexer to be virtual.

We want to create another class that also represents quarterly industrial production figures, but that instead will return a seasonally adjusted production figure. To simplify matters, seasonally adjusted here simply means that if the production figure is from the first or the second quarter (index 0 or 1 in the production array), add 50 to its value when requested; otherwise, deduct 30. We also want to include a property called TotalSeasonAdjusted, which returns the sum of the values in the production array with each of the quarterly figures being seasonally adjusted before it is added to the total.

To implement these functionalities, we create a new class called ProductionSeasonAdjust (lines 21 37) and derive it from the ProductionList class. The indexer defined in lines 23 37 overrides the indexer in ProductionList. If the requested index is less than two, it must return the value of the production array plus 50; if greater than or equal to 2, it must return the value of the production array minus 30. This poses a problem: Even though the production array is inherited by the ProductionSeasonAdjust, it was declared private in the ProductionList class, so we cannot access it directly from ProductionSeasonAdjust. The problem could be resolved if we could somehow call the indexer of the base class, because this indexer accesses production. Fortunately, the base-access construct does exactly this.

The base access construct consists of the keyword base followed by a pair of square brackets that encloses an index. It must be positioned in a function member of a derived class. The base access construct will invoke the indexer in the base class that has an index of the same type as the index of the base access construct. In our case, the following part of line 28 and 30


calls the indexer in lines 7 18 of the base class and passes along the value of its index parameter. Consequently base[index] becomes equal to the value returned from line 11 (production[index]). Thus, according to our seasonal adjustment requirements we need to add 50 to base[index] if index is less than 2; otherwise; we must deduct 30 from base[index] before the value is returned to the caller. This functionality is implemented in lines 27 31.

The TotalSesonalAdjusted property sums up the seasonally adjusted figures by calling the indexer of the class it resides inside (because it already returns seasonally adjusted figures as we have just seen) with the following call:


Notice its similarity to the base access construct base[index]. Whereas this[i] calls an indexer from the same class, base[index] calls an indexer defined in the base class.

The Main method inserts the value 100 into production[0] in line 60. It is then printed in lines 64 and 65, but with a seasonal adjustment of plus 50, which correctly results in 150 being printed. The TotalSeasonalAdjusted property correctly returns the result 1140, which is calculated as follows


The base access construct not only allows you to access base class indexers but also base class members, as you will see in the next section.


C# Primer Plus
C Primer Plus (5th Edition)
ISBN: 0672326965
EAN: 2147483647
Year: 2000
Pages: 286
Authors: Stephen Prata © 2008-2017.
If you may any questions please contact us: