Csharp/CSharp Tutorial/Class/Indexer

Материал из .Net Framework эксперт
Перейти к: навигация, поиск

Creating One-Dimensional Indexers

A one-dimensional indexer has this general form:


<source lang="csharp">element-type this[int index] {

       // The get accessor.
       get {
           // return the value specified by index 
       }
       
       // The set accessor.
       set {
           // set the value specified by index 
       }
   }</source>

Define both int and string indexer for a class

<source lang="csharp">using System; using System.Collections; using System.Collections.Specialized; public class MainClass {

 public static void Main()
 {
   EmployeeList carLot = new EmployeeList();
   
   carLot["A"] = new Employee("A");
   carLot["B"] = new Employee("B");
   carLot["C"] = new Employee("C");
   Employee zippy = carLot["C"];
   Console.WriteLine(zippy.Name);
 }

} public class EmployeeList {

 private ListDictionary carDictionary;
 
 public EmployeeList()
 {
   carDictionary = new ListDictionary();
 }
 // The string indexer.
 public Employee this[string name]
 {
   get { return (Employee)carDictionary[name];}
   set { carDictionary.Add(name, value);}
 }
 
 // The int indexer.
 public Employee this[int item]
 {
   get { return (Employee)carDictionary[item];}
   set { carDictionary.Add(item, value);}
 }

} public class Employee {

   public string Name = "";
   
 public Employee(string n)
 {
     Name = n;
 }

}</source>

C

Define getter only indexer

<source lang="csharp">using System; public class Employee {

 private string firstName;
 private string lastName;
 public Employee(string firstName, string lastName)
 {
   this.firstName = firstName;
   this.lastName = lastName;
 }
 public string this[int index]
 {
   get
   {
     switch (index)
     {
       case 0:
         return firstName;
       case 1:
         return lastName;
       default:
         throw new IndexOutOfRangeException();
     }
   }
 }

} class MainClass {

 public static void Main()
 {
   Employee myEmployee = new Employee("T", "M");
   Console.WriteLine("myEmployee[0] = " + myEmployee[0]);
   Console.WriteLine("myEmployee[1] = " + myEmployee[1]);
 }

}</source>

myEmployee[0] = T
myEmployee[1] = M

Indexer based on 0 or non-zero

<source lang="csharp">using System; class MyClass {

  int value0; 
  int value1; 
  public int this[int index] 
  {
     get
     {
        return (0 == index) ? value0 : value1;
     }
     set
     {
        if (0 == index)
           value0 = value; 
        else
           value1 = value; 
     }
  }

} class MainClass {

  static void Main()
  {
     MyClass a = new MyClass();
     Console.WriteLine("Values -- T0: {0}, T1: {1}", a[0], a[1]);
     a[0] = 15;
     a[1] = 20;
     Console.WriteLine("Values -- T0: {0}, T1: {1}", a[0], a[1]);
  }

}</source>

Values -- T0: 0, T1: 0
Values -- T0: 15, T1: 20

Indexer based on switch statement

<source lang="csharp">using System;

class MyClass {

  public string value0;             
  public string value1;            
  public string value2;          
  
  public string this[int index] 
  {
     set 
     {
        switch (index)
        {
           case 0: value0 = value;
              break;
           case 1: value1 = value;
              break;
           case 2: value2 = value;
              break;
        }
     }
     get 
     {
        switch (index)
        {
           case 0: return value0;
           case 1: return value1;
           case 2: return value2;
           default:
              return "";
        }
     }
  }

} class MainClass {

  static void Main()
  {
     MyClass myObject = new MyClass();
     myObject.value0 = "0";
     myObject.value1 = "1";
     myObject.value2 = "2";
     Console.WriteLine("{0}, {1}, {2}", myObject[0], myObject[1], myObject[2]);
  }

}</source>

0, 1, 2

Indexer for generic type

<source lang="csharp">using System.Collections; public abstract class Shape {

  public abstract void Draw();

} public class Rectangle : Shape {

  public override void Draw()
  {
     System.Console.WriteLine( "Rectangle.Draw" );
  }

} public class Circle : Shape {

  public override void Draw()
  {
     System.Console.WriteLine( "Circle.Draw" );
  }

} public class ShapeList {

  private ArrayList shapes;
  public ShapeList()
  {
     shapes = new ArrayList();
  }
  public int Count
  {
     get
     {
        return shapes.Count;
     }
  }
  public Shape this[ int index ]
  {
     get
     {
        return (Shape) shapes[index];
     }
  }
  public void Add( Shape shape )
  {
     shapes.Add( shape );
  }

} public class MainClass {

  static void Main()
  {
     ShapeList drawing = new ShapeList();
     drawing.Add( new Rectangle() );
     drawing.Add( new Circle() );
     
     for( int i = 0; i < drawing.Count; ++i ) {
        Shape shape = drawing[i];
        shape.Draw();
     }
  }

}</source>

Rectangle.Draw
Circle.Draw

Indexers don"t have to operate on actual arrays

<source lang="csharp">using System;

class MySequence {

 public int this[int index] { 
   get { 
     return index + 1; 
   } 

 } 

}

class MainClass {

 public static void Main() {  
   MySequence sequence = new MySequence(); 

   for(int i=0; i < 8; i++) 
     Console.Write(sequence[i] + " "); 
   Console.WriteLine(); 
 } 

}</source>

1 2 3 4 5 6 7 8

Indexing with an Integer Indexer

  1. It is possible to overload the [ ] operator for classes that you create with an indexer.
  2. An indexer allows an object to be indexed like an array.


<source lang="csharp">using System; using System.Collections; class Pair {

   public Pair(string name, object data)
   {
       this.name = name;
       this.data = data;
   }
   public string Name
   {
       get
       {
           return(name);
       }
       set
       {
           name = value;
       }
   }
   public object Data
   {
       get
       {
           return(data);
       }
       set
       {
           data = value;
       }
   }
   string    name;
   object data;

} class PairList {

   public PairList()
   {
       row = new ArrayList();
   }
   
   public void Load() 
   {
       /* load code here */ 
       row.Add(new Pair("A", 5551212));
       row.Add(new Pair("B", "Fred"));
       row.Add(new Pair("C", 2355.23m));
   }
   
   // the indexer
   public Pair this[int column]
   {
       get
       {
           return((Pair) row[column - 1]);
       }
       set
       {
           row[column - 1] = value;
       }
   }
   ArrayList    row;    

} class MainClass {

   public static void Main()
   {
       PairList row = new PairList();
       row.Load();
       Console.WriteLine("Column 0: {0}", row[1].Data);
       row[1].Data = 12;    
   }

}</source>

Column 0: 5551212

Indexing with an String Indexer

<source lang="csharp">using System; using System.Collections; class Pair {

   public Pair(string name, object data)
   {
       this.name = name;
       this.data = data;
   }
   public string Name
   {
       get
       {
           return(name);
       }
       set
       {
           name = value;
       }
   }
   public object Data
   {
       get
       {
           return(data);
       }
       set
       {
           data = value;
       }
   }
   string    name;
   object data;

} class PairList {

   public PairList()
   {
       row = new ArrayList();
   }
   
   public void Load() 
   {
       /* load code here */ 
       row.Add(new Pair("Q", 5551212));
       row.Add(new Pair("A", "text"));
       row.Add(new Pair("B", 2355.23m));
   }
   
   public Pair this[int column]
   {
       get
       {
           return( (Pair) row[column - 1]);
       }
       set
       {
           row[column - 1] = value;
       }
   }
   int FindPair(string name)
   {
       for (int index = 0; index < row.Count; index++)
       {
           Pair Pair = (Pair) row[index];
           if (Pair.Name == name)
           return(index);
       }
       return(-1);
   }
   public Pair this[string name]
   {
       get
       {
           return( (Pair) this[FindPair(name)]);
       }
       set
       {
           this[FindPair(name)] = value;
       }
   }
   ArrayList    row;    

} class Test {

   public static void Main()
   {
       PairList row = new PairList();
       row.Load();
       Pair val = row["A"];
       Console.WriteLine("A: {0}", val.Data);
       Console.WriteLine("B: {0}", row["B"].Data);
       row["Q"].Data = "new value";    // set the name
       Console.WriteLine("Q: {0}", row["Q"].Data);
   }

}</source>

A: 5551212
B: text
Unhandled Exception: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negativ
e and less than the size of the collection.
Parameter name: index
   at System.Collections.ArrayList.get_Item(Int32 index)
   at PairList.get_Item(Int32 column)
   at Test.Main()

Indexing with Multiple Parameters

<source lang="csharp">using System; public class Cell {

   string name;
   
   public Cell(string name)
   {
       this.name = name;
   }
   
   public override string ToString()
   {
       return(name);
   }

} public class Table {

   Cell[,] table = new Cell[8, 8];
   
   int RowToIndex(string row)
   {
       string temp = row.ToUpper();
       return((int) temp[0] - (int) "A");
   }
   
   int PositionToColumn(string pos)
   {
       return(pos[1] - "0" - 1);
   }
   
   public Cell this[string row, int column]
   {
       get
       {
           return(table[RowToIndex(row), column - 1]);
       }
       set
       {
           table[RowToIndex(row), column - 1] = value;
       }
   }    
   
   public Cell this[string position]
   {
       get
       {
           return(table[RowToIndex(position),
           PositionToColumn(position)]);
       }
       set
       {
           table[RowToIndex(position),
           PositionToColumn(position)] = value;
       }
   }    

} class MainClass {

   public static void Main()
   {
       Table table = new Table();
       
       table["A", 4] = new Cell("A4");
       table["H", 4] = new Cell("H4");
       
       Console.WriteLine("A4 = {0}", table["A", 4]);
       Console.WriteLine("H4 = {0}", table["H4"]);
   }

}</source>

A4 = A4
H4 = H4

Overload the MyArray indexer

<source lang="csharp">using System;

class MyArray {

 int[] a;    
 
 public int Length;
 
 public bool errflag;
   
 public MyArray(int size) {  
   a = new int[size];  
   Length = size;   
 }  
 
 // This is the int indexer for MyArray.  
 public int this[int index] {  
   get {  
     if(indexCheck(index)) {  
       errflag = false;  
       return a[index];  
     } else {  
       errflag = true;  
       return 0;  
     }  
   }  
 
   set {  
     if(indexCheck(index)) {  
       a[index] = value;  
       errflag = false;  
     }  
     else errflag = true;  
   }  
 }  
 
 public int this[double idx] {  
   get {  
     int index = (int) idx; 

     if(indexCheck(index)) {  
       errflag = false;  
       return a[index];  
     } else {  
       errflag = true;  
       return 0;  
     }  
   }  
 
   set {  
     int index = (int) idx; 

     if(indexCheck(index)) {  
       a[index] = value;  
       errflag = false;  
     }  
     else errflag = true;  
   }  
 }  
 
 private bool indexCheck(int index) {  
  if(index >= 0 & index < Length) return true;  
  return false;  
 }  

}

class MainClass {

 public static void Main() {   
   MyArray myArray = new MyArray(5);  
 
   for(int i=0; i < myArray.Length; i++) 
     myArray[i] = i;  

   // now index with ints and doubles 
   Console.WriteLine("myArray[1]: " + myArray[1]); 
   Console.WriteLine("myArray[2]: " + myArray[2]); 

   Console.WriteLine("myArray[1.1]: " + myArray[1.1]); 
   Console.WriteLine("myArray[1.6]: " + myArray[1.6]); 

 }  

}</source>

myArray[1]: 1
myArray[2]: 2
myArray[1.1]: 1
myArray[1.6]: 1

Use an indexer to create a fail-soft array.

<source lang="csharp">using System;

class MyArray {

 int[] a;

 public int Length; 

 public bool errflag;
  
 public MyArray(int size) { 
   a = new int[size]; 
   Length = size;  
 } 

 // This is the indexer for MyArray. 
 public int this[int index] { 
   get { 
     if(indexCheck(index)) { 
       errflag = false; 
       return a[index]; 
     } else { 
       errflag = true; 
       return 0; 
     } 
   } 

   set { 
     if(indexCheck(index)) { 
       a[index] = value; 
       errflag = false; 
     } 
     else errflag = true; 
   } 
 } 

 private bool indexCheck(int index) { 
  if(index >= 0 & index < Length) 
     return true; 
  return false; 
 } 

}

class MainClass {

 public static void Main() {  
   MyArray myArray = new MyArray(5); 
   int x; 

   Console.WriteLine("Fail quietly."); 
   for(int i=0; i < 10; i++) 
     myArray[i] = i*10; 

   for(int i=0; i < 10; i++) { 
     x = myArray[i]; 
     if(x != -1) Console.Write(x + " "); 
   } 
   Console.WriteLine(); 

   Console.WriteLine("\nFail with error reports."); 
   for(int i=0; i < 10; i++) { 
     myArray[i] = i*10; 
     if(myArray.errflag) 
       Console.WriteLine("myArray[" + i + "] out-of-bounds"); 
   } 

   for(int i=0; i < 10; i++) { 
     x = myArray[i]; 
     if(!myArray.errflag) 
        Console.Write(x + " "); 
     else 
        Console.WriteLine("myArray[" + i + "] out-of-bounds"); 
   } 
 } 

}</source>

Fail quietly.
0 10 20 30 40 0 0 0 0 0
Fail with error reports.
myArray[5] out-of-bounds
myArray[6] out-of-bounds
myArray[7] out-of-bounds
myArray[8] out-of-bounds
myArray[9] out-of-bounds
0 10 20 30 40 myArray[5] out-of-bounds
myArray[6] out-of-bounds
myArray[7] out-of-bounds
myArray[8] out-of-bounds
myArray[9] out-of-bounds

Use indexer to add element

<source lang="csharp">using System; using System.Collections; public class MainClass {

 public static void Main()
 {
   EmployeeList empList = new EmployeeList();
 
   empList[0] = new Employee("F");
   empList[1] = new Employee("C");
   empList[2] = new Employee("Z");
   for(int i = 0; i < empList.GetNumberOfEmployeeList(); i++)
   {
     Console.WriteLine("Employee number {0}:", i);
     Console.WriteLine("Name: {0}", empList[i].Name);
   }
   try
   {
     Console.WriteLine("Using IEnumerable");
     foreach (Employee c in empList)
     {
       Console.WriteLine("Name: {0}", c.Name);
     }
   }
   catch{}      
 }

} public class EmployeeList : IEnumerable {

 private ArrayList carArray;
 public EmployeeList()
 {
   carArray = new ArrayList();
 }
 // The indexer.
 public Employee this[int pos]
 {
   get
   {
     if(pos < 0)
       throw new IndexOutOfRangeException("Hey! Index out of range");
     else
       return (Employee)carArray[pos];
   }
   set
   {
     carArray.Insert(pos, value);
   }
 }
 public int GetNumberOfEmployeeList()
 {
   return carArray.Count;
 }
 public IEnumerator GetEnumerator()
 {
   return carArray.GetEnumerator();
 }

} public class Employee {

 public Employee(string name)
 {
   this.Name = name;
 }
 public string Name;

}</source>

Employee number 0:
Name: F
Employee number 1:
Name: C
Employee number 2:
Name: Z
Using IEnumerable
Name: F
Name: C
Name: Z