C#阶段提高之---索引器
索引器允许类或结构的实例就像数组一样进行索引。索引器类似于属性,不同之处在于它们的访问器采用参数。除下表中显示的差别外,为属性访问器定义的所有规则同样适用于索引器访问器。
属性 |
索引器 |
---|---|
允许像调用公共数据成员一样调用方法。 |
允许对一个对象本身使用数组表示法来访问该对象内部集合中的元素。 |
可通过简单的名称进行访问。 |
可通过索引器进行访问。 |
可以为静态成员或实例成员。 |
必须为实例成员。 |
属性的 get 访问器没有参数。 |
索引器的 get 访问器具有与索引器相同的形参表。 |
属性的 set 访问器包含隐式 value 参数。 |
除了 值参数外,索引器的 set 访问器还具有与索引器相同的形参表。 |
支持对 自动实现的属性(get;set;)使用短语法。 |
不支持短语法(必须完整)。 |
1):一般属性索引器
要声明类或结构上的索引器,请使用 this 关键字,如下例所示,声明一个int类型的索引器:
1: public int this[int index] // Indexer declaration
2: {
3: // get and set accessors
4: }
索引器的签名由其形参的数量和类型组成。它不包括索引器类型或形参名。如果在同一类中声明一个以上的索引器,则它们必须具有不同的签名。这就是索引器的重载,与函数方法的重载性质一样。下面通过一个简单的例子说明索引器:
1: public class Person
2: {
3: //索引器可以重载
4: public string this[string input]
5: {
6: get
7: {
8: if (input == "Name")
9: {
10: return this.Name;
11: }
12: else if (input == "Age")
13: {
14: return this.Age.ToString();
15: }
16: else
17: {
18: return null;
19: }
20: }
21: set
22: {
23: if (input == "Name")
24: {
25: this.Name = value;
26: }
27: else if (input == "Age")
28: {
29: this.Age = Convert.ToInt32(value);
30: }
31: }
32: }
33: public string Name {get; set; }
34: public int Age{set;get;}
35: }
在这里我们定义了一个Person类,里面声明两个属性,在索引器中set与get中分别对属性进行操作。在使用中我们直接可以通过p[XX]调用索引器。
1: static void Main(string[] args)
2: {
3: Person p = new Person() {Name="zhang",Age=16};
4: Console.WriteLine("请输入你要访问的属性:");
5: string a = Console.ReadLine();
6: // 通过p[a]调用索引器
7: Console.WriteLine(p[a]);
8: }
input: Name
Output:zhang
究竟索引器的书写到底是为了什么呢?上面的例子已经清楚地说明:索引器就是为了对象能够直接中括号访问他的成员加!
再举一个例子:
1: public int[] arr = new int[10];
2: public int this[int index]
3: {
4: get
5: {
6: return arr[index];
7: }
8: }
本来说组的访问是要arr[index],然而如果这个说组在Person的Class中,在外部访问就要对象加点访问数组,然后数组下标访问数组的值就是这样
1: Person p=new Person();
2: //数组加点访问成员
3: p.arr[0]=123;
如果我们现在有了索引器的话,上面代码的索引器数组,那么访问数组就变得简单,因为索引器已经将对象的成员封装。访问如下:
1: Person p=new Person();
2: //直接对像[数组下标]搞定!
这就是索引器的基础精华部分。
2):接口索引器
另外索引器还在接口时间使用叫做接口索引器。接口访问器不使用修饰符。接口访问器没有体。因此,访问器的用途是指示索引器是读写、只读还是只写。
以下是接口索引器访问器的示例:
1: public interface ISomeInterface
2: {
3: // Indexer declaration:
4: int this[int index]
5: {
6: get;
7: set;
8: }
9: }
下面是显示实现接口索引器:
1: // 实现接口
2: class IndexerClass : ISomeInterface
3: {
4: private int[] arr = new int[100];
5: public int this[int index] // 索引器声明
6: {
7: get
8: {
9: // The arr object will throw IndexOutOfRange exception.
10: return arr[index];
11: }
12: set
13: {
14: arr[index] = value;
15: }
16: }
17: }
完全符合接口的性质,考虑在Main函数的调用将如何呢?
1: static void Main()
2: {
3: IndexerClass test = new IndexerClass();
4: //随机数字
5: System.Random rand = new System.Random();
6: for (int i = 0; i < 10; i++)
7: {
8: //对于每一数组的值赋值一个随机的变量
9: test[i] = rand.Next();
10: }
11: for (int i = 0; i < 10; i++)
12: {
13: //怎么定义的怎么给我输出来,索引器的强大之处
14: System.Console.WriteLine("Element #{0} = {1}", i, test[i]);
15: }
16: System.Console.ReadKey();
17: }
这样的数组赋值你感觉如何呢?
至于索引器用在何处是个很好的话题,我认为索引器一般是用于封装内部集合或数组的类型。