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

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

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**

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

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

4. ​**Dictionary**

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

Dictionary ages = new Dictionary();
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**

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

SortedList list = new SortedList();
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 内置,多维索引
字符串(string int char 只读
List int T 动态扩容
Dictionary TKey TValue 键查找高效
DataRow int 或 string object 支持列名和列索引
自定义类 任意类型(可多参数) 任意类型 可封装复杂逻辑

注意事项

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

你可能感兴趣的:(学习,c#,面向对象,封装)