【C#进阶】C# 索引器

序号 系列文章
13 【C#进阶】C# 特性
14 【C#进阶】C# 反射
15 【C#进阶】C# 属性

文章目录

  • 前言
  • 1、索引器的概念
  • 2、索引器的定义
  • 3、索引器的基本使用
  • 4、索引器的重载
  • 5、接口中的索引器
  • 6、属性和索引器之间的比较
  • 7、索引器的适用场景
  • 结语

前言

Hello大家好啊,我是作家桑。本文为大家介绍 C# 中的索引器。


1、索引器的概念

索引器允许类或结构的实例就像数组一样进行索引。无需显式指定类型或实例成员,即可通过运算符[]设置或检索索引值。索引器类似于属性,不同的是索引器的访问器需要使用参数。

2、索引器的定义

在 C# 中可以使用 this 关键字作为属性名声明索引器,并在方括号内声明参数。索引器也可以使用 C# 中任何有效的访问修饰符,在索引器中为 get 和 set 访问器前指定不同的访问修饰符即可。和属性的定义一样,索引器内也需要定义 get 和 set 访问器,其中 get 访问器返回值。 set 访问器分配值。

示例代码:

public int this[string key]
{
    get { return storage.Find(key); }
    set { storage.SetAt(key, value); }
}
  • 其中方括号内的参数 key 表示调用索引器时的索引值
  • value 参数是 set 访问器里内置的,表示调用索引器时的分配值

你也可以编写只读索引器(忽略 set 访问器)或只写索引器(忽略 get 访问器)。

只读索引器:

// 忽略 set 访问器
public int this[string key]
{
    get { return storage.Find(key); }
}

只写索引器:

// 忽略 get 访问器
public int this[string key]
{
    set { storage.SetAt(key, value); }
}

3、索引器的基本使用

索引器可以方便地在类、结构体和接口上创建,以便调用方程序可以像数组一样访问它们。在定义好索引器之后,基本的使用就是通过[]运算符对索引器进行访问和对元素进行赋值。

示例代码:

using System;

public class Indexedweek
{
    string[] weekarray = new string[daysCount];
    static int daysCount = 7; 


    public Indexedweek()
    {
        for (int i = 0; i < daysCount; i++)
            weekarray[i] = "Week";
    }

    // 定义索引器 
    public string this[int index]
    {
        get
        {
            string week;        
                            
            if (index >= 0 && index <= daysCount - 1)
                week = weekarray[index];         
            else
                week = "";      
                    
            return week;
        }
        set
        {
            if (index >= 0 && index <= daysCount - 1)
                weekarray[index] = value;
        }
    }

    static void Main(string[] args)
    {
        Indexedweek weeks = new Indexedweek();
        weeks[0] = "Monday";
        weeks[1] = "Tuesday";
        weeks[2] = "Wednesday";
        weeks[3] = "Thursday";
        weeks[4] = "Friday";
        weeks[5] = "Saturday";
        weeks[6] = "Sunday";

        for (int i = 0; i < Indexedweek.daysCount; i++)
        {
            Console.WriteLine(weeks[i]);
        }

        Console.ReadLine();
    }
}

运行结果:
【C#进阶】C# 索引器_第1张图片
在上面的示例中,我们使用关键字 this 定义了索引器。其中 get 访问器用于输出 weekarray 数组中的元素,set 访问器用于将指定的 value 值赋值给 weekarray 数组。在 Main 方法中就可以直接使用[]运算符调用我们定义的索引器的功能。

4、索引器的重载

不仅是方法,索引器也可被重载。虽然索引器和属性类似,但是在索引器的参数上可区分索引器和属性。只要分别对索引器的参数声明不同的类型,就可以在类中创建使用一个或多个索引器。

以上面计算星期天数的代码为示例。

代码示例:

// 定义索引器 
public string this[int index]
{
    get
    {
        string week;
				
        if (index >= 0 && index <= daysCount - 1)
            week = weekarray[index];
        else
            week = "";

        return week;
    }
    set
    {
        if (index >= 0 && index <= daysCount - 1)
            weekarray[index] = value;
    }
}

// 重载索引器
public int this[string myWeek]
{
    get
    {
        int index = 0; 

        while(index < daysCount)
        {
            if (weekarray[index] == myWeek)
            {
                return index;
            }       
            index++;
        }
        return -1;      // 返回-1表示没有找到
    }
}
// 返回数组中指定元素的索引值
Console.WriteLine(weeks["Sunday"]);

运行结果:
【C#进阶】C# 索引器_第2张图片

5、接口中的索引器

索引器不仅可以在类和结构体中实现,也可以在接口中创建。但是接口索引器的访问器与类索引器的访问器有所不同,有以下两个差异:

  • 接口访问器不使用修饰符
  • 接口访问器通常没有正文

虽然接口中的索引器可以被实现,但是这种情况非常少见。索引器通常定义 API1 来访问数据字段,而数据字段无法在接口中定义。

代码示例:

//接口上的索引器
public interface IIndexInterface
{
    // 索引器声明
    int this[int index]
    {
        get;
        set;
    }
}

// 实现接口
class IndexerClass : IIndexInterface
{
    private int[] arr = new int[100];
    public int this[int index]   // 实现接口中的索引器
    {
        get => arr[index];
        set => arr[index] = value;
    }

    static void Main(string[] args)
    {
        IndexerClass test = new IndexerClass();
        int count = 1; 

        //调用索引器初始化它的元素。 
        for (int i = 0; i < 10; i++)
        {
            test[i] = count;
            count++;
        }

        for (int i = 0; i < 10; i++)
        {
            System.Console.WriteLine($"元素 #{i} = {test[i]}");
        }
    }
}

运行结果:
【C#进阶】C# 索引器_第3张图片

6、属性和索引器之间的比较

索引器与属性相似,以一个表格来展示两者之间的差别。除了这些差别之外,对属性访问器定义的所有规则也适用于索引器访问器。

表格如下:

属性 索引器
允许以将方法视作公共数据成员的方式调用方法。 通过在对象自身上使用数组表示法,允许访问对象内部集合的元素。
通过简单名称访问。 通过索引访问。
可为静态成员或实例成员。 必须是实例成员。
属性的 get 访问器没有任何参数。 索引器的 get 访问器具有与索引器相同的形参列表。
属性的 set 访问器包含隐式 value 参数。 索引器的 set 访问器具有与索引器相同的形参列表,value 参数也是如此。
通过自动实现的属性支持简短语法。 支持仅使用索引器的 expression-bodied2 成员。

7、索引器的适用场景

列举一些索引器在程序中的适用场景,借此可以对索引器有一个更好的理解。

  • 需要简化接口在类中集合的访问时,索引器也是一种语法糖3
  • 类表示的是对象的列表、集合或数组时
  • 当类型需要对数组或矢量进行建模时
  • 需要对字典数据或映射进行建模时

点击了解更多索引器的使用。


结语

以上就是 C# 索引器的介绍啦,希望对大家有所帮助。感谢大家的支持。


  1. API: 全称 Application Programming Interface,即应用程序编程接口。是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件的以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。 ↩︎

  2. Expression-bodied: 是将 lambda 表达式的这种用法扩展到了方法、属性等成员上,表示成员的实现。 ↩︎

  3. 语法糖(syntactic sugar): 是指编程语言中可以更容易的表达一个操作的语法,它可以使程序员更加容易去使用这门语言。语法糖使得操作可以变得更加清晰、方便,或者更加符合程序员的编程习惯。 ↩︎

你可能感兴趣的:(C#/.NET系列文章,c#,开发语言,.net,微软,.netcore)