SIGN UP MEMBER LOGIN:    
ARTICLE

Value based Indexer

Posted by Sivaraman Dhamodaran Articles | C# Language October 30, 2010
This article talks about value based indexing.
Reader Level:
Download Files:
 

Please read the article which explains about Position based Indexing: http://www.c-sharpcorner.com/UploadFile/6897bc/4037/Default.aspx

  1. This article talks about value based indexing.
  2. To know about the Product and SuperMarket class please read the article specified above
Simple Value based Indexer for SuperMarket Class

The previous indexer locates the memory block based on the Index by calculating the offset, as it knows the size of the memory block.  Now we will implement value-based index; that is we will get the product based on the ProductId value. I will walk through the changes done on the Classes.

1) The product class changed to have a setter method for ProductName, and a getter method for ProductId and an overridden method for ToString just to print Product Name. Following are the Changes:

public
override string ToString()
{
    return ProductName;
}
public int GetProductId()
{
    return ProductId;
}
public void SetProductName(string newName)
{        
    ProductName = newName;
}

2) In the SuperMarketX class a variable called numeric_index_mode is declared. This variable is used to decide the Indexer is referred in Positional Mode or in Value mode.

public
int numeric_index_mode; //0-Position based index. 1-Value based Index.


Inside the constructor, indexer mode is initialized to 0. That means SuperMarket class by default treats the Indexer as Positional indexer and retrieves the product based on the positional offset calculated.

numeric_index_mode = 0;

3) A public function is implemented to retrieve the Positional index for the passed-in Product Id. Note, that the product id is unique for this Value based Index. The function will iterate through the Products in the SuperMarket and return when Product Id matched. It will return –1 when match not occurred. Following is the new function implemented to support the value-based index:

//005: Supporting function for value based Index
public int GetProduct(int Productid)
{
    for (int i = 0; i < Products.Length; i++)
    {
        Product p = Products[i];
        if ( p != null )
        {
            int prodid = p.GetProductId();
            if (prodid == Productid)
                return i; 
        }
    }
    return -1;
}

Now lets go and change the Indexer.

1) First in the get portion of the Indexer, wrap the existing code with an if construct. That is; when the Mode = 0, go with positional Index. It holds true for Set portion of the Indexer also. Below is the Change:

get
{
    //003_1: Retrieve Product based on positional index
    if (numeric_index_mode == 0)
    {
        if (index >= Products.Length || index < 0 ) 
        {
            return null;
        }
        return Products[index];
}
set
{
    //003_2: Set the value based on the positional index
    if (numeric_index_mode == 0 )
    {
        if (index >= Products.Length )
        {
            return;
        }
        Products[index] = value ;
}

2) If we are in Value mode, In the Get part of the indexer first get the positional index for the given product id. Once we have the positional index, we are ready to make recursive call to same indexer routine. Make sure to set the indexer mode to 0 as we need to access the indexer to get the product based on the indexed position. Once we have the Product, reset index mode back to 1; that reset indexer mode to value based as the client code would expect that.

Following is the Code for get portion:

//003_2: Retrieve Product based on the Unique product Id
if(numeric_index_mode == 1)
{
    int idx = GetProduct(index);
    if (idx == -1)
        return null;
    else
    {
        //Key statement to avoid invalid recursion
        numeric_index_mode = 0;
        Product ret_Product = this[idx]; //Recursive call to Indexer
        numeric_index_mode = 1; //Reset it back to user preference
        return ret_Product;
    }
}

3) Set portion of the Indexer also changed in the same way. I hope further explanation is not required:

//003_3: Set the value based on the Id Passed in.
if(numeric_index_mode == 1)
{
    int idx = GetProduct(index);
    if (idx == -1)
        return ;
    else
    {
        //Key statement to avoid invalid recursion
        numeric_index_mode = 0;
        Products[idx] = value;
        numeric_index_mode = 1; //Reset it back to user preference
    }
}

Usage of Value based indexer

Code below explains how do we switch from Position based indexer to Value based indexer, use value based indexer and go back to default indexer mode. The commented code is self-explanatory. Hence no more explanation. Dot.

//=====> Value based Index     <=======
//Now we will operate on the Value based Index
market.numeric_index_mode = 1;
//Client 006: Display name of the product whose product id is 1005
Console.WriteLine("Name of the Product represented by Id 1005 is: {0}", market[1016]);

//Client 007: The aim is Replace the Product Soda with Iced Soda and maintain same product id. The Id of Soda is 1002.
if (market[1002] != null )
{
    market[1002].SetProductName("Iced Soda");
    Console.WriteLine("Product Available in Super Market: " + market );
}

//Client 008: Remove Tea and Add French Coffee. Note the Object in the Indexed location will be changed.
//Note: Here check for the null is not required. Kind of Modify on fail Add
market[1003] = new Product(1007, "French Coffee");
Console.WriteLine("Product Available in Super Market: " + market );

//======> Reset back to Standard Positional Index    <=================
market.numeric_index_mode = 0;

Closing Notes

1) You can implement string value based indexer also. The skeleton is:

public
Product this[string ProductName]
{
    Set{}
    Get{}
}

2) As our positional based index takes the index as integer, we introduced numeric_index_mode. If I implement string-based index the mode switching is not required. The alternate implementation for the Value based product id is convert the product id into string and use string based index.

Attachments

Indexer_src: Source code for indexer.
Indexer_exe: Executable for Indexer. Run it in the command prompt. Map the output with the following client code:

class
ProgramEntry
{
    [STAThread]
    static void Main(string[] args)
    {
        //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() );

        
//=====> Value based Index     <=======
        //Now we will operate on the Value based Index
        market.numeric_index_mode = 1;

        //Client 006: Display name of the product whose product id is 1005
        Console.WriteLine("Name of the Product represented by Id 1005 is: {0}", market[1016]);

        
//Client 007: The aim is Replace the Product Soda with Iced Soda and maintain same product id. The Id of Soda is 1002.
        if (market[1002] != null )
        {
            market[1002].SetProductName("Iced Soda");
            Console.WriteLine("Product Available in Super Market: " + market );
        }

        
//Client 008: Remove Tea and Add French Coffee. Note the Object in the Indexed location will be changed.
        //Note: Here check for the null is not required. Kind of Modify on fail Add
        market[1003] = new Product(1007, "French Coffee");
        Console.WriteLine("Product Available in Super Market: " + market );

        
//======> Reset back to Standard Positional Index    <=================
        market.numeric_index_mode = 0;
        //Dot
    }
}

Login to add your contents and source code to this article
share this article :
post comment
 
Nevron Gauge for SharePoint
Become a Sponsor
PREMIUM SPONSORS
  • Get 2 Months Free of ASP.NET Hosting for Only $4.95/month! Receive FREE MS SQL and MySQL Databases Including ASP.NET 4/3.5, MVC 3.0, Silverlight 4, Windows 2008/IIS 7.0 Plus FREE IIS 7 Modules. Host UNLIMITED ASP.NET Web Sites - Click Here!
    Get 2 Months Free of ASP.NET Hosting for Only $4.95/month! Receive FREE MS SQL and MySQL Databases Including ASP.NET 4/3.5, MVC 3.0, Silverlight 4, Windows 2008/IIS 7.0 Plus FREE IIS 7 Modules. Host UNLIMITED ASP.NET Web Sites - Click Here!
Nevron Gauge for SharePoint
Become a Sponsor