C# 索引器 使用详解

server/2025/2/21 10:22:43/

总目录


前言

在 C# 中,数组和集合可以通过索引直接访问元素,例如 arr[0]。但如果想让自定义的类或结构体也支持这种直观的访问方式,该怎么办?这时,索引器(Indexer) 就派上用场了!索引器是 C# 中一个强大但常被忽视的特性,它能为你的类型赋予类似数组的访问能力,同时隐藏底层数据结构的复杂性。本文将深入探讨索引器的语法、应用场景及高级技巧,并通过大量示例代码帮助你彻底掌握这一特性。


一、索引器是什么?

1. 基本概念

  • 索引器允许类或结构的实例就像数组一样进行索引。 无需显式指定类型或实例成员,即可设置或检索索引值。 索引器类似于属性,不同之处在于它们的访问器需要使用参数。
  • 索引器是一种特殊成员,允许类或结构体通过索引(如 obj[0])访问其内部数据。它的核心作用是为类型提供类似数组或字典的访问接口,从而简化代码逻辑,提升可读性。

2. 索引器与属性的区别

  • 属性(Property):通过名称访问,例如 obj.Name
  • 索引器(Indexer):通过索引(参数)访问,例如 obj[0]obj["key"]
    索引器支持多参数,而属性没有参数。

在这里插入图片描述

3. 索引器有什么用?

在C#开发中,我们经常需要操作包含集合数据的自定义类型。传统方法通过Get/Set方法访问元素不仅繁琐,还破坏了代码的简洁性。索引器(Indexer)正是为解决这个问题而生,它允许我们使用类似数组的语法([])来访问对象内部集合,极大提升了代码的可读性和易用性。

二、索引器的使用

1. 索引器的定义

索引器使用 this 关键字定义,语法如下:

public 返回类型 this[参数类型 参数]
{get { /* 获取逻辑 */ }set { /* 设置逻辑 */ }
}

2. 基本操作

示例 1:普通对象中的使用

    public class Person{private string _name, _pwd, _phone;public string Name{get { return _name; }set { _name = value; }}public string Pwd{get { return _pwd; }set { _pwd = value; }}public string Phone{get { return _phone; }set { _phone = value; }}//通过this关键字定义索引器,this代表的就是当前对象的实例,[]内就是索引器的参数列表public string this[int index]{get{if (index == 0) return _name;else if (index == 1) return _pwd;else if (index == 2) return _phone;else return null;}set{if (index == 0) _name = value;else if (index == 1) _pwd = value;else if (index == 2) _phone = value;}}}static void Main(string[] args){//使用实例的属性赋值和取值Person p = new Person();p.Name = "AAA";p.Pwd = "111";p.Phone = "11111111111";Console.WriteLine($"属性取值:Name={p.Name} Pwd={p.Pwd} Phone={p.Phone}");//使用实例的索引器赋值和取值Person person = new Person();person[0] = "BBB";person[1] = "222";person[2] = "222222222";Console.WriteLine($"索引器取值:Name={person[0]} Pwd={person[1]} Phone={person[2]}");Console.ReadLine();}

上面的案例通过定义一个索引器,来索引类中的每一个属性,使得我们可以使用类似于 person[0]的方式访问类中每一个属性并进行赋值和取值。

示例 2:封装数组的索引器

public class StringArray
{private string[] _array = new string[10];public string this[int index]{get => _array[index];set => _array[index] = value;}
}// 使用示例
var arr = new StringArray();
arr[0] = "Hello";  // 调用 set 访问器
Console.WriteLine(arr[0]);  // 输出 "Hello"

示例 3:多维索引器

索引器的参数可以是 intstring 或其他类型(支持任意类型的参数),甚至支持多参数(多维索引器)。

public class Grid
{private int[,] _grid = new int[10, 10];public int this[int row, int col]{get => _grid[row, col];set => _grid[row, col] = value;}
}// 使用示例
var grid = new Grid();
grid[3, 4] = 100;  // 设置二维索引的值

3. 进阶操作

1) 读写控制

索引器可以仅暴露 getset,实现只读或只写:

public class ReadOnlyList
{private int[] _data = { 1, 2, 3 };// 只读索引器(省略 set)public int this[int index] => _data[index];
}

2) 重载索引器

一个类可以定义多个索引器,通过参数类型或数量区分:

public class MultiIndexer
{private List<string> _names = new List<string> { "Alice", "Bob" };// 通过 int 索引获取名字public string this[int index] => _names[index];// 通过名字查找索引public int this[string name] => _names.IndexOf(name);
}// 使用示例
var indexer = new MultiIndexer();
Console.WriteLine(indexer[0]);      // 输出 "Alice"
Console.WriteLine(indexer["Bob"]);  // 输出 1

3) 动态逻辑处理

getset 中添加自定义逻辑(如数据验证):

public class SafeArray
{private int[] _array = new int[10];public int this[int index]{get{if (index < 0 || index >= _array.Length)throw new IndexOutOfRangeException();return _array[index];}set{if (index < 0 || index >= _array.Length)throw new IndexOutOfRangeException();_array[index] = value;}}
}

4) 接口中的索引器

索引器可以在接口中定义,由实现类具体实现:

public interface IArrayContainer
{int this[int index] { get; set; }
}public class MyArray : IArrayContainer
{private int[] _array = new int[10];public int this[int index]{get => _array[index];set => _array[index] = value;}
}

四、索引器的应用场景

1. 封装集合类

自定义集合类时,索引器可提供类似原生数组的访问方式:

public class CustomList<T>
{private T[] _items = new T[10];private int _count = 0;public T this[int index]{get => _items[index];set => _items[index] = value;}public void Add(T item) => _items[_count++] = item;
}

在这里插入图片描述

2. 多维数据或复杂结构 访问

例如矩阵、网格或表格数据的封装。以下示例是封装温度数据,通过日期索引访问:

public class TemperatureData
{private float[] _temperatures = new float[365];public float this[DateTime date]{get => _temperatures[date.DayOfYear - 1];set => _temperatures[date.DayOfYear - 1] = value;}
}// 使用示例
var tempData = new TemperatureData();
tempData[new DateTime(2023, 7, 1)] = 35.5f;

3. 替代冗余方法

简化类似 GetValue(int index)SetValue(int index, T value) 的方法调用。

// 没有索引器的写法
var value = list.GetValue(0);
list.SetValue(0, "New Value");// 使用索引器的写法
var value = list[0];
list[0] = "New Value";

五、注意事项

  • 命名规则
    索引器只能命名为 this,不能自定义名称。

  • 静态索引器
    C# 不支持静态索引器(如 public static int this[int index])。

  • 性能优化
    避免在索引器中实现复杂逻辑(如数据库查询),尤其是在高频访问场景中。

  • 异常处理
    始终验证索引的有效性,避免抛出未处理的 IndexOutOfRangeException

  • 索引器与属性的区别

    • 属性通过名称访问(如 obj.Name),索引器通过索引访问(如 obj[0])。
    • 索引器可以有多个参数,属性没有参数。

合理使用索引器可以让代码更优雅,但需注意避免过度设计。如果你正在开发自定义集合或需要为类型提供直观的访问接口,索引器将是一个得力的工具!


结语

回到目录页:C#/.NET 知识汇总
希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。


参考资料:
C# 官方文档 - 索引器


http://www.ppmy.cn/server/169532.html

相关文章

angular中使用animation.css实现翻转展示卡片正反两面效果

html <div(click)"flip()"class"animate__animated cursor--pointer"[ngClass]"{ animate__flipInX: isFlipped }" ><div *ngIf"!isFlipped">正面</div><div *ngIf"isFlipped">背面</div> …

vscode复制到下一行

linux中默认快捷键是ctrl shift alt down/up 但是在vscode中无法使用&#xff0c;应该是被其他的东西绑定了&#xff0c;经测试&#xff0c;可以使用windows下的快捷键shift alt down/up { “key”: “shiftaltdown”, “command”: “editor.action.copyLinesDownAction”…

组件二次封装

基于ui组件库的二次封装 对组件进行二次封装主要有以下几个原因&#xff1a; 提高复用性&#xff1a;通过封装通用组件&#xff0c;可以在多个地方复用&#xff0c;减少代码重复&#xff0c;提高开发效率。统一风格和规范&#xff1a;确保所有使用该组件的地方都遵循统一的风…

查看cmd下python的安装路径 + Windows 命令行添加环境变量和不重启刷新环境变量

1、查看cmd下python的安装路径 cmd ----》输入“python” 命令 ---》输入 import sys; print(sys.executable) 即可看到当前系统python的安装路径&#xff1a; 注&#xff1a;系统所使用的python实际上就是在系统环境变量下配置的python目录。 2、刷新path命令&#xff1a;在c…

Debezium:实时数据捕获与同步的利器

一、什么是 Debezium Debezium 是一个开源的分布式平台&#xff0c;专门用于捕获数据库中的数据变更。它通过读取数据库的事务日志&#xff0c;能够以非侵入性的方式捕获数据库中发生的所有变化&#xff0c;并将这些变化转化为事件流&#xff0c;实时推送到像 Kafka 这样的消息…

从入门到精通:Postman 实用指南

Postman 是一款超棒的 API 开发工具&#xff0c;能用来测试、调试和管理 API&#xff0c;大大提升开发效率。下面就给大家详细讲讲它的安装、使用方法&#xff0c;再分享些实用技巧。 一、安装 Postman 你能在 Postman 官网&#xff08;https://www.postman.com &#xff09;下…

[生活杂项][运动教程]自由泳

https://v.youku.com/v_show/id_XMzgzMjkwMzg0MA.html?spma2h0k.11417342.soresults.dtitle https://v.youku.com/v_show/id_XMzgxNjM2NjY4NA.html?spma2h0k.11417342.soresults.dtitle

鸿蒙-状态管理V2

目录 前言综述ComponentV2ObservedV2和TraceLocalParamOnceEventMonitorComputed 前言 前面我们讲了状态管理V1相关装饰器和注意事项&#xff0c;一般来讲是足够在开发中使用了&#xff0c;但还是有一些不方便的地方&#xff0c;因此又有了状态管理 V2。 截止到现在&#xff0…