当前位置: 首页 > news >正文

C#核心学习(五)面向对象--封装(4)C#中的索引器详解:让对象像数组一样灵活访问

        

目录

一、C#中的索引器是什么?

二、索引器有什么作用?

1. 增强封装性

2. 提升代码可读性

3. 支持复杂逻辑

三、怎么进行申明

        基础语法

重载索引器

四、总结

核心价值

适用场景

注意事项

1. ​数组(Array)​

2. ​字符串(string)​

3. ​**List**

4. ​**Dictionary**

5. ​**DataRow(ADO.NET)​**

6. ​**SortedList**

7. ​自定义类型(类/结构体)​

注意事项


        在C#编程中,你是否遇到过这样的场景:封装了一个复杂的数据结构,却希望它能像数组一样通过[]符号被轻松访问?或者想要为自定义类型赋予类似ListDictionary的直观元素操作体验?

        索引器(Indexer)正是为此而生。它不仅是C#语法中的一颗“语法糖”,更是一种提升代码表现力的利器。通过索引器,开发者可以隐藏底层数据结构的复杂性,以一致、简洁的语法对外暴露数据访问逻辑。无论是遍历多维矩阵、快速查询键值对,还是为业务模型定制特殊的数据规则,索引器都能让代码变得更加优雅且易于维护。

        本文将从核心概念实际作用实现细节,带你全面掌握C#索引器的使用技巧,并通过常见数据类型(如数组、字典、DataRow等)的案例,揭示其灵活性与实用性。无论你是刚接触索引器的新手,还是希望深化理解的开发者,这里都有你需要的答案。

一、C#中的索引器是什么?

        索引器(Indexer)是C#中一种特殊的成员,允许对象像数组一样通过索引值进行数据访问。它本质上是对对象下标操作符([])的重载,使得开发者可以为自定义类型(如类或结构体)定义类似数组的访问行为。索引器的核心特点是用参数化的属性语法封装内部数据,从而提供更直观的数据访问方式。

        例如,当我们需要像访问数组元素一样访问一个自定义集合对象的元素时,可以通过索引器实现:

MyCollection collection = new MyCollection();
Console.WriteLine(collection[0]); // 通过索引器访问

二、索引器有什么作用?

1. 增强封装性

        通过索引器隐藏内部数据结构(如数组、字典等)的实现细节,对外提供统一的访问接口。例如,一个封装数据库查询结果的类可以通过索引器暴露数据行:

        

public class QueryResult {
    private DataRow[] _rows;
    public DataRow this[int index] => _rows[index];
}

2. 提升代码可读性

        使自定义类型的元素访问语法与内置类型(如数组、列表)一致,降低学习成本:

// 传统方法 vs 索引器
var value1 = myObj.GetValueAt(5);  // 方法调用
var value2 = myObj[5];             // 索引器调用

3. 支持复杂逻辑

        可以在getset访问器中添加验证、计算、缓存等逻辑:

public class TemperatureData {
    private float[] _temps;
    public float this[int day] {
        get { return _temps[day % 7]; }  // 实现循环访问
        set { _temps[day % 7] = value; }
    }
}

三、怎么进行申明

        基础语法

public class MyClass {
    // 声明索引器
    //     返回类型          参数类型        索引
    public ReturnType this[ParameterType index] {
        get { /* 返回值逻辑 */ }
        set { /* 赋值逻辑 */ }
    }
}

示例:二维索引器

public class Matrix {
    private int[,] _matrix = new int[10,10];
    public int this[int row, int col] {
        get => _matrix[row, col];
        set => _matrix[row, col] = value;
    }
}

// 使用
Matrix m = new Matrix();
m[3,5] = 100;

重载索引器

        支持通过不同参数类型或数量进行重载:

public class MultiIndexer {
    // 整数索引
    public string this[int index] { ... }
    
    // 字符串索引
    public string this[string key] { ... }
    
    // 多参数索引
    public int this[int x, int y] { ... }
}

四、总结

核心价值

  • 使自定义类型拥有类似数组的访问语法
  • 增强代码的可维护性和扩展性
  • 支持参数化数据访问逻辑

适用场景

  • 封装集合类(如自定义List/Dictionary)
  • 多维数据访问(如矩阵、表格)
  • 需要验证或处理访问逻辑的场合

注意事项

  • 避免过度使用导致代码可读性下降
  • 优先考虑使用现有集合类型(如List<T>

        其实在前面我们就已经学到过一些索引器了,接下来我举几个看看: 

1. ​数组(Array)​

        所有C#数组(一维、多维、交错数组)均内置索引器,通过整型索引访问元素:

// 一维数组
int[] numbers = { 10, 20, 30 };
Console.WriteLine(numbers[0]); // 输出 10

// 二维数组
int[,] matrix = new int[2, 2] { { 1, 2 }, { 3, 4 } };
Console.WriteLine(matrix[1, 0]); // 输出 3

// 交错数组(数组的数组)
int[][] jagged = { new int[] { 1 }, new int[] { 2, 3 } };
Console.WriteLine(jagged[1][0]); // 输出 2

2. ​字符串(string)​

        字符串通过索引器直接访问字符(只读,因字符串不可变):

string text = "Hello";
char firstChar = text[0]; // 'H'
// text[0] = 'h'; // 错误!字符串不可修改

3. ​**List<T>**

        泛型列表通过整型索引访问元素,支持动态扩容:

List<string> names = new List<string> { "Alice", "Bob" };
Console.WriteLine(names[1]); // 输出 "Bob"
names[0] = "Alex"; // 修改元素

4. ​**Dictionary<TKey, TValue>**

        字典通过键(任意类型)作为索引参数访问值:

Dictionary<string, int> ages = new Dictionary<string, int>();
ages["Alice"] = 25;
Console.WriteLine(ages["Alice"]); // 输出 25

5. ​**DataRow(ADO.NET)​**

   DataRow 通过列名或列索引访问单元格数据:

DataTable table = new DataTable();
table.Columns.Add("Name", typeof(string));
table.Rows.Add("Alice");

DataRow row = table.Rows[0];
string name1 = row["Name"];   // 列名索引
string name2 = row[0];        // 列索引(整型)

6. ​**SortedList<TKey, TValue>**

        有序列表同时支持通过键和整型索引访问元素:

SortedList<int, string> list = new SortedList<int, string>();
list.Add(3, "Three");
list.Add(1, "One");

Console.WriteLine(list[3]);       // 键索引 → "Three"
Console.WriteLine(list.Values[0]); // 整型索引 → "One"(按排序顺序)

7. ​自定义类型(类/结构体)​

        自定义类型声明索引器,支持任意参数类型和逻辑:

public class ColorPalette {
    private string[] _colors = { "Red", "Green", "Blue" };
    
    // 整型索引器
    public string this[int index] {
        get => _colors[index];
        set => _colors[index] = value;
    }
    
    // 字符串索引器(通过名称获取颜色)
    public int this[string name] {
        get => Array.IndexOf(_colors, name);
    }
}

// 使用
ColorPalette palette = new ColorPalette();
Console.WriteLine(palette[0]);    // 输出 "Red"
Console.WriteLine(palette["Blue"]); // 输出 2
数据类型索引器参数类型返回值类型特点
数组(int[]int元素类型(如 int内置,多维索引
字符串(stringintchar只读
List<T>intT动态扩容
Dictionary<TKey,TValue>TKeyTValue键查找高效
DataRowint 或 stringobject支持列名和列索引
自定义类任意类型(可多参数)任意类型可封装复杂逻辑

注意事项

  1. ​内置索引器不可修改:如数组、字符串的索引器是系统实现的,无法自定义。
  2. ​索引越界:大多数索引器在访问无效索引时会抛出 IndexOutOfRangeException 或 KeyNotFoundException(字典)。
  3. ​性能:字典的索引器(通过键查找)时间复杂度为 O(1),而线性查找的索引器(如 List.IndexOf)为 O(n)。
http://www.dtcms.com/a/108317.html

相关文章:

  • MySQL的数据目录以及日志
  • 企业网络优化方案:SD-WAN赋能企业远程办公
  • 使用JSON.stringify报错:Uncaught TypeError: cyclic object value
  • RNN模型与NLP应用——(6/9)Text Generation(文本自动生成)
  • UE小:在Unreal Engine 5中实现多层静态网格体遮挡拾取
  • 【落羽的落羽 C++】模板简介
  • 交易引擎中的设计模式
  • 「青牛科技」GC5331 5V三相无感正弦波电机驱动芯片 对标茂达APX9331/灿瑞OCH2360
  • Spring Cloud Gateway 的核心作用
  • Flutter项目之登录注册功能实现
  • Debian/Ubuntu的networking的`/etc/network/interfaces`配置文件,如何配置route路由
  • SQL问题分析与诊断(8)——关键信息(2)
  • 数据结构----栈
  • LangChain/Eliza框架在使用场景上的异同,Eliza通过配置实现功能扩展的例子
  • 【力扣hot100题】(036)二叉树的最大深度
  • Spring Boot 工程创建详解
  • 小游戏中Enable Exceptions的各选项有何区别
  • 基于开源AI大模型与S2B2C模式的线下服务型门店增长策略研究——以AI智能名片与小程序源码技术为核心
  • 从静态到动态:D * 算法如何革新机器人路径规划
  • 图形渲染: tinyrenderer 实现笔记(Lesson 1 - 4)
  • ATEngin开发记录_1_在Vsiual Studio2022中使用ReShaper创建类模板
  • 理解激活函数,多个网络层之间如何连接
  • 红宝书第二十七讲:详解WebAssembly与asm.js如何实现高效执行
  • 七种分布式ID生成方式详细介绍--Redis、雪花算法、号段模式以及美团Leaf 等
  • 二分查找与二分答案入门c++
  • 如何对后端API进行负载测试
  • vue将组件中template转为js
  • codeforces C. Creating Keys for StORages Has Become My Main Skill
  • systemd服务开机启动(code=exited, status=203/EXEC)错误,由于SELinux 开启安全模式
  • AI知识补全(十五):AI可解释性与透明度是什么?