(为类或结构的实例建立索引)
索引器使您得以按照与数组相同的方式为类或结构实例建立索引。若要声明索引器,请使用以下方式:
[attributes] [modifiers] indexer-declarator {accessor-declarations}
indexer-declarator 采用下列形式之一:
type this [formal-index-parameter-list] type interface-type.this [formal-index-parameter-list]
formal-index-parameter 采用的形式为:
[attributes] type identifier
其中:
索引器的 get 访问器体与方法体类似。它返回索引器的类型。get 访问器使用与索引器相同的 formal-index-parameter-list。例如:
get { return myArray[index]; }
索引器的 set 访问器体与方法体类似。除了 value 隐式参数外,它还使用与索引器相同的 formal-index-parameter-list。例如:
set { myArray[index] = value; }
索引器的类型和 formal-index-parameter-list 中引用的每个类型必须至少与索引器本身一样是可访问的。有关可访问级别的更多信息,请参见访问修饰符。
索引器的签名由其形参的数量和类型组成。它不包括索引器类型或形参名。
如果在同一类中声明一个以上的索引器,则它们必须具有不同的签名。
索引器值不作为变量来分类;因此,不可能将索引器值作为 ref 或 out 参数来传递。
若要为索引器提供可由其他语言用于默认索引属性的名称,可在声明中使用 name 属性。例如:
[System.Runtime.CompilerServices.CSharp.IndexerName("MyItem")] public int this [int index] // Indexer declaration { }
此索引器将具有名称 MyItem
。如果不提供 name 属性,则默认名称为 Item
。
以下示例说明如何声明私有数组字段、myArray
和索引器。通过使用索引器可直接访问实例 b[i]
。另一种使用索引器的方法是将数组声明为 public 成员并直接访问它的成员 myArray[i]
。
// cs_keyword_indexers.cs using System; class IndexerClass { private int [] myArray = new int[100]; public int this [int index] // Indexer declaration { get { // Check the index limits. if (index < 0 || index >= 100) return 0; else return myArray[index]; } set { if (!(index < 0 || index >= 100)) myArray[index] = value; } } } public class MainClass { public static void Main() { IndexerClass b = new IndexerClass(); // Call the indexer to initialize the elements #3 and #5. b[3] = 256; b[5] = 1024; for (int i=0; i<=10; i++) { Console.WriteLine("Element #{0} = {1}", i, b[i]); } } }
Element #0 = 0 Element #1 = 0 Element #2 = 0 Element #3 = 256 Element #4 = 0 Element #5 = 1024 Element #6 = 0 Element #7 = 0 Element #8 = 0 Element #9 = 0 Element #10 = 0
注意,当计算索引器的访问时(例如,在 Console.Write 语句中),调用 get 访问器。因此,如果 get 访问器不存在,将发生编译时错误。
当索引器声明包含 extern
修饰符时,称该索引器为外部索引器。因为外部索引器声明不提供任何实际的实现,所以它的每个访问器声明都由一个分号组成。
下面的示例声明了一个 BitArray
类,该类实现了一个索引器,用于访问位数组中的单个位。
using System; class BitArray { int[] bits; int length; public BitArray(int length) { if (length < 0) throw new ArgumentException(); bits = new int[((length - 1) >> 5) + 1]; this.length = length; } public int Length { get { return length; } } public bool this[int index] { get { if (index < 0 || index >= length) { throw new IndexOutOfRangeException(); } return (bits[index >> 5] & 1 << index) != 0; } set { if (index < 0 || index >= length) { throw new IndexOutOfRangeException(); } if (value) { bits[index >> 5] |= 1 << index; } else { bits[index >> 5] &= ~(1 << index); } } } }
BitArray
类的实例所占的内存远少于相应的 bool[]
(这是由于前者的每个值只占一位,而后者的每个值要占一个字节),而且,它可以执行与 bool[]
相同的操作。
下面的 CountPrimes
类使用 BitArray
和经典的“筛选”算法计算 1 和给定的最大数之间质数的数目:
class CountPrimes { static int Count(int max) { BitArray flags = new BitArray(max + 1); int count = 1; for (int i = 2; i <= max; i++) { if (!flags[i]) { for (int j = i * 2; j <= max; j += i) flags[j] = true; count++; } } return count; } static void Main(string[] args) { int max = int.Parse(args[0]); int count = Count(max); Console.WriteLine("Found {0} primes between 1 and {1}", count, max); } }
请注意,访问 BitArray
的元素的语法与访问 bool[]
的元素的语法完全相同。
下列示例显示一个具有带两个参数的索引器的 26 乘 10 网格类。第一个参数必须是 A–Z 范围内的大写或小写字母,而第二个参数必须是 0–9 范围内的整数。
using System; class Grid { const int NumRows = 26; const int NumCols = 10; int[,] cells = new int[NumRows, NumCols]; public int this[char c, int col] { get { c = Char.ToUpper(c); if (c < 'A' || c > 'Z') { throw new ArgumentException(); } if (col < 0 || col >= NumCols) { throw new IndexOutOfRangeException(); } return cells[c - 'A', col]; } set { c = Char.ToUpper(c); if (c < 'A' || c > 'Z') { throw new ArgumentException(); } if (col < 0 || col >= NumCols) { throw new IndexOutOfRangeException(); } cells[c - 'A', col] = value; } } }