索引器允许类或结构的实例就像数组一样进行索引。 无需显式指定类型或实例成员,即可设置或检索索引值。 索引器类似于属性),不同之处在于它们的访问器需要使用参数。
以下示例定义了一个泛型类,其中包含用于赋值和检索值的简单get和 set访问器方法。 Program
类创建了此类的一个实例,用于存储字符串。
using System; class SampleCollection<T> { // Declare an array to store the data elements. private T[] arr = new T[100]; // Define the indexer to allow client code to use [] notation. public T this[int i] { get { return arr[i]; } set { arr[i] = value; } } } class Program { static void Main() { var stringCollection = new SampleCollection<string>(); stringCollection[0] = "Hello, World"; Console.WriteLine(stringCollection[0]); } } // The example displays the following output: // Hello, World.
表达式主体定义
索引器的 get 或 set 访问器包含一个用于返回或设置值的语句很常见。 为了支持这种情况,表达式主体成员提供了一种经过简化的语法。 自 C# 6 起,可以表达式主体成员的形式实现只读索引器,如以下示例所示。
using System; class SampleCollection<T> { // Declare an array to store the data elements. private T[] arr = new T[100]; int nextIndex = 0; // Define the indexer to allow client code to use [] notation. public T this[int i] => arr[i]; public void Add(T value) { if (nextIndex >= arr.Length) throw new IndexOutOfRangeException($"The collection can hold only {arr.Length} elements."); arr[nextIndex++] = value; } } class Program { static void Main() { var stringCollection = new SampleCollection<string>(); stringCollection.Add("Hello, World"); System.Console.WriteLine(stringCollection[0]); } } // The example displays the following output: // Hello, World.
请注意,=>
引入了表达式主体,并未使用 get
关键字。
自 C# 7.0 起,get 和 set 访问器均可作为表达式主体成员实现。 在这种情况下,必须使用 get
和 set
关键字。 例如:
using System; class SampleCollection<T> { // Declare an array to store the data elements. private T[] arr = new T[100]; // Define the indexer to allow client code to use [] notation. public T this[int i] { get => arr[i]; set => arr[i] = value; } } class Program { static void Main() { var stringCollection = new SampleCollection<string>(); stringCollection[0] = "Hello, World."; Console.WriteLine(stringCollection[0]); } } // The example displays the following output: // Hello, World.
索引器概述
- 使用索引器可以用类似于数组的方式为对象建立索引。
-
get
取值函数返回值。set
取值函数分配值。 - this关键字用于定义索引器。
- value 关键字用于定义由
set
访问器分配的值。 - 索引器不必根据整数值进行索引;由你决定如何定义特定的查找机制。
- 索引器可被重载。
- 索引器可以有多个形参,例如当访问二维数组时。
索引器的使用
索引器使你可从语法上方便地创建类、结构或接口,以便客户端应用程序可以像访问数组一样访问它们。 编译器将生成一个 Item 属性(或者如果存在 IndexerNameAttribute,也可以生成一个命名属性)和适当的访问器方法。 在主要目标是封装内部集合或数组的类型中,常常要实现索引器。 例如,假设有一个类 TempRecord,它表示 24 小时的周期内在 10 个不同时间点所记录的温度(单位为华氏度)。 此类包含一个 float[] 类型的数组 temps,用于存储温度值。 通过在此类中实现索引器,客户端可采用 float temp = tempRecord 的形式(而非 float temp = tempRecord.temps)访问 TempRecord 实例中的温度。 索引器表示法不但简化了客户端应用程序的语法;还使类及其目标更容易直观地为其它开发者所理解。
若要在类或结构上声明索引器,请使用 this 关键字,如以下示例所示:
// Indexer declaration public int this[int index] { // get and set accessors }
通过声明索引器,可自动在对象上生成一个名为 Item 的属性。 无法从实例成员访问表达式直接访问 Item 属性。 此外,如果通过索引器向对象添加自己的 Item 属性,则将收到 CS0102 编译器错误。 要避免此错误,请使用 IndexerNameAttribute 来重命名索引器,详细信息如下所示。
下面的示例声明了存储星期几的类。 get 访问器采用字符串(星期几)并返回对应的整数。 例如,“Sunday”返回 0,“Monday”返回 1,依此类推。
// Using a string as an indexer value class DayCollection { string[] days = ["Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"]; // Indexer with only a get accessor with the expression-bodied definition: public int this[string day] => FindDayIndex(day); private int FindDayIndex(string day) { for (int j = 0; j < days.Length; j++) { if (days[j] == day) { return j; } } throw new ArgumentOutOfRangeException( nameof(day), $"Day {day} is not supported.\nDay input must be in the form \"Sun\", \"Mon\", etc"); } }
下面的示例声明了使用 System.DayOfWeek 存储星期几的类。 get 访问器采用 DayOfWeek(表示星期几的值)并返回对应的整数。 例如,DayOfWeek.Sunday 返回 0,DayOfWeek.Monday 返回 1,依此类推。
using Day = System.DayOfWeek; class DayOfWeekCollection { Day[] days = [ Day.Sunday, Day.Monday, Day.Tuesday, Day.Wednesday, Day.Thursday, Day.Friday, Day.Saturday ]; // Indexer with only a get accessor with the expression-bodied definition: public int this[Day day] => FindDayIndex(day); private int FindDayIndex(Day day) { for (int j = 0; j < days.Length; j++) { if (days[j] == day) { return j; } } throw new ArgumentOutOfRangeException( nameof(day), $"Day {day} is not supported.\nDay input must be a defined System.DayOfWeek value."); } }
更多实例可参考官方文档
索引器和属性
索引器与属性相似。 除下表所示的差别外,对属性访问器定义的所有规则也适用于索引器访问器。
索引器与属性相似。 除下表所示的差别外,对属性访问器定义的所有规则也适用于索引器访问器。
Property | 索引器 |
---|---|
允许以将方法视作公共数据成员的方式调用方法。 | 通过在对象自身上使用数组表示法,允许访问对象内部集合的元素。 |
通过简单名称访问。 | 通过索引访问。 |
可为静态成员或实例成员。 | 必须是实例成员。 |
属性的 get 访问器没有任何参数 | 索引器的get 访问器具有与索引器相同的形参列表 |
属性的 set访问器包含隐式 value 参数。 |
索引器的 set 访问器具有与索引器相同的形参列表,value 参数也是如此。 |
通过自动实现的属性支持简短语法。 | 支持仅使用索引器的 expression-bodied 成员。 |