Introduction
We all know that an Array is nothing but sequential memory locations in which data is stored. Let us say that the size of the continuous memory is 80 KB and that the size of one unit of data is 2 KB. The statement implies that we have an array of 40 items in sequential memory locations. The below picture shows the above explanation:
For Example, Consider the below Array:
Department dpt = new Department[40];
If we assume the size required to store each department is 2 KB, we have 40 blocks of size 2 KB for each department object. Also note that 40 objects are allocated in sequential order. So, how do we get the object at the third memory block? We do use the below statement:
Dpt[2]. What is [2] represents here? It says take the object from the third memory block. So here, each memory blocks are referred by the Indexed location. So the notation [] is what called Indexer.
In this article, we will see how we can implement a Simple position based Indexer for our collection class. In the next article we will explore, how we can implement Value based index.
The Product Class
Consider the below specified simple class which represents the products for a retail shop. It has two private data members; a constructor and a public method to retrieve the product name.
//001: Product Class.
public class Product
{
private int ProductId;
private string ProductName;
public Product(int id, string Name)
{
ProductId = id;
ProductName = Name;
}
public string GetProdName()
{
return ProductName;
}
}
The SuperMarket Class
As every super market has a collection of products, this class is going to have a collection of product objects. The members of this class is shown below:
//002: SuperMarket has collection of products. It implements Indexers.
public class SuperMarketX
{
//002_1: Declaration
private int pos;
private Product[] Products;
"Pos" is to iterate through the Products collection. OK, you might have the idea now. SuperMarket is a user defined (defined by us now) collection of Products.
The constructor of this class will take an array of products as parameter and assigns it to the private member Products. Note, that for this article, I am allocating fixed space 1000 and each space has null reference initially. We will replace the null reference with the passed in array of objects. Below is the code for the Constructor:
//002_2: Constructor
public SuperMarketX(string shopname, params Product[] products)
{
//002_2.1: Allocate the Space required
this.Products = new Product[1000];
pos = 0;
//002_2.2: first set null to all the elements
for (int i=0; i< 1000; i++)
Products[i] = null;
//002_2.3: Assign the Array by taking the references from incoming array.
//The reference will replace the previous null assignment
foreach (Product prd in products)
{
Products[pos] = prd;
pos++;
}
this.shopname = shopname;
}
We have overridden the ToString() method to get the entire product in comma-separated format. The method implementation is shown below:
//004: Override the ToString to display all the Product Names as Comma Separated List
public override string ToString()
{
string returnval = "";
foreach (Product p in Products )
{
if ( p != null )
returnval = returnval + "," + p.GetProdName();
}
//Cut the leading "," and return
return returnval.Substring(1, returnval.Length-1 );
}
Simple Position based Indexer for SuperMarket Class
The indexer is implemented just like the correesponding overloaded function. To implement the [] notation follow the below syntax:
public <ReturnType> this[<datatype> index]
Ex:
public Product this[int index]
Get an integer index from the caller and return a Product.
The Implementation Skeleton on the Simple Indexer is shown below:
In our case, we will implement the Index for the Supermarket. So using the Positional Index, a product will be retrieved. The way the index implemented will give a null reference to caller when index is out of range; say below 0 or above 1000(This is the Maximum product supported by the super market). Below is the function implementation:
//003: The Use of Indexer. Positional Indexer
public Product this[int index]
{
get
{
//003_1: Retrieve value based on positional index
if (index >= Products.Length || index < 0 )
{
return null;
}
return Products[index];
}
set
{
//003_2: Set the value based on the positional index
if (index >= Products.Length )
{
return;
}
Products[index] = value ;
}
}
Indexer Usage
Have a look at the below Code:
//Client 001: First Let us create an array to hold 6 Products.
Product[] theProdArray = new Product[6];
//Client 002: Create 6 individual Product and store it in the array
theProdArray[0] = new Product(1001, "Beer");
theProdArray[1] = new Product(1002, "Soda");
theProdArray[2] = new Product(1003, "Tea");
theProdArray[3] = new Product(1004, "Coffee");
theProdArray[4] = new Product(1005, "Apple");
theProdArray[5] = new Product(1006, "Grapes");
//Client 003: Super Market that holds six product collection
SuperMarketX market = new SuperMarketX("Z Stores", theProdArray);
Console.WriteLine("Product Available in Super Market: " + market );
//Client 004: Use the Simple Indexer to Assign the value
market[15] = new Product(1015, "Orange");
Console.WriteLine("Product Available in Super Market: " + market );
//Client 005: Use the Simple Indexer to retrieve the value
Product prod = market[5];
Console.WriteLine("The product retrieved is: " + prod.GetProdName() );
Below is the Explanation
- Client 001: Creates the Array 6 Product.
- Client 002: Populates the product array. [In real world Array will be populated from Database]
- Client 003: SuperMarket is created with 6 New Products. Note that out super market capacity is 1000.
- Client 004: Uses the Indexer to add new product to the Products collection. market[15] = new Product(1015, "Orange"); Will call the indexer with index = 15. new Product(1015, "Orange"); will be referred in the set portion of the Indexer using the value keyword.
- Client 005: Product prod = market[5]; SuperMarket Object accessed with Indexer [5]. We will move to get portion of the Indexer and indexer returns Product at the position offset 5. The return object reference is assigned to prod.