Export (0) Print
Expand All
81 out of 119 rated this helpful - Rate this topic

Indexers Tutorial

Visual Studio .NET 2003

This tutorial shows how C# classes can declare indexers to provide array-like access to the classes.

Sample Files

See Indexers Sample to download and build the sample files discussed in this tutorial.

Further Reading

Tutorial

Defining an indexer allows you to create classes that act like "virtual arrays." Instances of that class can be accessed using the [] array access operator. Defining an indexer in C# is similar to defining operator [] in C++, but is considerably more flexible. For classes that encapsulate array- or collection-like functionality, using an indexer allows the users of that class to use the array syntax to access the class.

For example, suppose you want to define a class that makes a file appear as an array of bytes. If the file were very large, it would be impractical to read the entire file into memory, especially if you only wanted to read or change a few bytes. By defining a FileByteArray class, you could make the file appear similar to an array of bytes, but actually do file input and output when a byte was read or written.

In addition to the example below, an advanced topic on Creating an Indexed Property is discussed in this tutorial.

Example

In this example, the class FileByteArray makes it possible to access a file as if it were a byte array. The Reverse class reverses the bytes of the file. You can run this program to reverse the bytes of any text file including the program source file itself. To change the reversed file back to normal, run the program on the same file again.

// indexer.cs
// arguments: indexer.txt
using System;
using System.IO;

// Class to provide access to a large file
// as if it were a byte array.
public class FileByteArray
{
    Stream stream;      // Holds the underlying stream
                        // used to access the file.
// Create a new FileByteArray encapsulating a particular file.
    public FileByteArray(string fileName)
    {
        stream = new FileStream(fileName, FileMode.Open);
    }

    // Close the stream. This should be the last thing done
    // when you are finished.
    public void Close()
    {
        stream.Close();
        stream = null;
    }

    // Indexer to provide read/write access to the file.
    public byte this[long index]   // long is a 64-bit integer
    {
        // Read one byte at offset index and return it.
        get 
        {
            byte[] buffer = new byte[1];
            stream.Seek(index, SeekOrigin.Begin);
            stream.Read(buffer, 0, 1);
            return buffer[0];
        }
        // Write one byte at offset index and return it.
        set 
        {
            byte[] buffer = new byte[1] {value};
            stream.Seek(index, SeekOrigin.Begin);
            stream.Write(buffer, 0, 1);
        }
    }

    // Get the total length of the file.
    public long Length 
    {
        get 
        {
            return stream.Seek(0, SeekOrigin.End);
        }
    }
}

// Demonstrate the FileByteArray class.
// Reverses the bytes in a file.
public class Reverse 
{
    public static void Main(String[] args) 
    {
        // Check for arguments.
        if (args.Length == 0)
        {
            Console.WriteLine("indexer <filename>");
            return;
        }

        FileByteArray file = new FileByteArray(args[0]);
        long len = file.Length;

        // Swap bytes in the file to reverse it.
        for (long i = 0; i < len / 2; ++i) 
        {
            byte t;

            // Note that indexing the "file" variable invokes the
            // indexer on the FileByteStream class, which reads
            // and writes the bytes in the file.
            t = file[i];
            file[i] = file[len - i - 1];
            file[len - i - 1] = t;
        }

        file.Close();
    } 
}

Input: indexer.txt

To test the program you can use a text file with the following contents (this file is called Test.txt in the Indexers Sample).

public class Hello1
{
   public static void Main()
   {
      System.Console.WriteLine("Hello, World!");
   }
}

To reverse the bytes of this file, compile the program and then use the command line:

indexer indexer.txt

To display the reversed file, enter the command:

Type indexer.txt

Sample Output

}
}
;)"!dlroW ,olleH"(eniLetirW.elosnoC.metsyS
{
)(niaM diov citats cilbup
{
1olleH ssalc cilbup

Code Discussion

  • Since an indexer is accessed using the [] operator, it does not have a name. For indexer declaration syntax, see Indexers.
  • In the example above, the indexer is of type byte and takes a single index of type long (64-bit integer). The Get accessor defines the code to read a byte from the file, while the Set accessor defines the code to write a byte to the file. Inside the Set accessor, the predefined parameter value has the value that is being assigned to the virtual array element.
  • An indexer must have at least one parameter. Although it is comparatively rare, an indexer can have more than one parameter in order to simulate a multidimensional "virtual array." Although integral parameters are the most common, the indexer parameter can be of any type. For example, the standard Dictionary class provides an indexer with a parameter of type Object.
  • Although indexers are a powerful feature, it is important to use them only when the array-like abstraction makes sense. Always carefully consider whether using regular method(s) would be just as clear. For example, the following is a bad use of an indexer:
    class Employee
    {
        // VERY BAD STYLE: using an indexer to access
        // the salary of an employee.
        public double this[int year] 
       {
            get 
            {
                // return employee's salary for a given year.
            }
       }
    }
    

    Although legal, an indexer with only a Get accessor is rarely good style. Strongly consider using a method in this case.

  • Indexers can be overloaded (for more information, see 10.8.1 Indexer overloading).

See Also

C# Tutorials

Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback
Show:
© 2014 Microsoft. All rights reserved.