C# 索引器 详解(含对照例子)

发布于:2024-11-28 ⋅ 阅读:(13) ⋅ 点赞:(0)

索引器 是 C# 中的一种特殊成员,允许你像访问数组那样,通过索引来访问对象的元素。它使得在类或结构中以集合的方式获取或设置值变得更加直观。

主要特点:

  • 语法:索引器使用 this 关键字。
  • 可访问性:可以使用不同的访问修饰符(如 public、private 等)。
  • 类型:索引器可以接受多个参数并返回任意数据类型。
  • 重载:可以为同一类定义多个索引器,使其能够根据不同的参数来访问不同类型的数据

声明索引器的基本语法如下:

public class ClassName
{
    // 声明索引器
    public Type this[Type index]
    {
        get { /* 返回索引处的元素 */ }
        set { /* 设置索引处的元素 */ }
    }
}

索引器支持多个参数,语法如下:

public class MultiDimensionalArray
{
    private int[,] array = new int[5, 5];

    public int this[int row, int column]
    {
        get { return array[row, column]; }
        set { array[row, column] = value; }
    }
}

使用索引器对集合操作

1. 不使用索引器的版本

首先,先来看看不使用索引器怎么对集合进行操作:

using System;
using System.Collections.Generic;

public class NumberCollection
{
    private List<int> numbers = new List<int>();

    // 添加数字到集合
    public void Add(int number) 
    {
        numbers.Add(number);
    }

    // 获取指定索引的数字
    public int Get(int index)
    {
        return numbers[index];
    }

    // 设置指定索引的数字
    public void Set(int index, int value)
    {
        numbers[index] = value;
    }

    // 获取集合的数量
    public int Count
    {
        get { return numbers.Count; }
    }
}

// 使用不带索引器的版本
public class Program
{
    public static void Main()
    {
        NumberCollection collection = new NumberCollection();
        collection.Add(10);
        collection.Add(20);

        // 使用 Get 方法访问数字
        int number = collection.Get(0); // 直接通过方法访问
        Console.WriteLine($"Number at index 0: {number}");
        
        // 使用 Set 方法修改数字
        collection.Set(0, 30);
        number = collection.Get(0);
        Console.WriteLine($"Updated number at index 0: {number}");
    }
}

不适用索引器的情况下,通过 GetSet 方法来访问和修改集合中的元素。

2. 使用索引器的版本

using System;
using System.Collections.Generic;

public class NumberCollection
{
    private List<int> numbers = new List<int>();

    // 索引器定义
    public int this[int index]
    {
        get { return numbers[index]; }
        set { numbers[index] = value; }
    }

    // 添加数字到集合
    public void Add(int number) 
    {
        numbers.Add(number);
    }

    // 获取集合的数量
    public int Count
    {
        get { return numbers.Count; }
    }
}

// 使用索引器的版本
public class Program
{
    public static void Main()
    {
        NumberCollection collection = new NumberCollection();
        collection.Add(10);
        collection.Add(20);

        // 使用索引器访问数字
        int number = collection[0]; // 直接通过索引访问
        Console.WriteLine($"Number at index 0: {number}");
        
        // 使用索引器修改数字
        collection[0] = 30;
        number = collection[0];
        Console.WriteLine($"Updated number at index 0: {number}");
    }
}

使用索引器直接通过索引访问和修改集合中的元素。这种方式使得代码更加直观,减少了方法调用的数量,提升了可读性。

二维索引器示例

1. 使用索引器的版本

在此版本中,使用索引器来访问和修改矩阵中的元素。

using System;

public class Matrix
{
    private int[,] elements;

    // 构造函数,初始化矩阵的大小
    public Matrix(int rows, int cols)
    {
        elements = new int[rows, cols];
    }

    // 索引器定义
    public int this[int row, int col]
    {
        get { return elements[row, col]; }
        set { elements[row, col] = value; }
    }

    // 获取行数
    public int Rows => elements.GetLength(0);

    // 获取列数
    public int Columns => elements.GetLength(1);
}

// 使用索引器的版本
public class Program
{
    public static void Main()
    {
        Matrix matrix = new Matrix(3, 3); // 创建一个 3x3 矩阵
        matrix[0, 0] = 1; // 使用索引器设置值
        matrix[0, 1] = 2;
        matrix[0, 2] = 3;

        // 读取并打印矩阵中的值
        for (int i = 0; i < matrix.Rows; i++)
        {
            for (int j = 0; j < matrix.Columns; j++)
            {
                Console.Write(matrix[i, j] + " "); // 使用索引器访问值
            }
            Console.WriteLine();
        }
    }
}

2. 不使用索引器的版本

在这个版本中,使用方法来访问和修改矩阵中的元素,而不是使用索引器。

using System;

public class MatrixWithoutIndexer
{
    private int[,] elements;

    // 构造函数,初始化矩阵的大小
    public MatrixWithoutIndexer(int rows, int cols)
    {
        elements = new int[rows, cols];
    }

    // 设置元素的值
    public void SetElement(int row, int col, int value)
    {
        elements[row, col] = value;
    }

    // 获取元素的值
    public int GetElement(int row, int col)
    {
        return elements[row, col];
    }

    // 获取行数
    public int Rows => elements.GetLength(0);

    // 获取列数
    public int Columns => elements.GetLength(1);
}

// 使用不带索引器的版本
public class ProgramWithoutIndexer
{
    public static void Main()
    {
        MatrixWithoutIndexer matrix = new MatrixWithoutIndexer(3, 3); // 创建一个 3x3 矩阵
        matrix.SetElement(0, 0, 1); // 使用方法设置值
        matrix.SetElement(0, 1, 2);
        matrix.SetElement(0, 2, 3);

        // 读取并打印矩阵中的值
        for (int i = 0; i < matrix.Rows; i++)
        {
            for (int j = 0; j < matrix.Columns; j++)
            {
                Console.Write(matrix.GetElement(i, j) + " "); // 使用方法访问值
            }
            Console.WriteLine();
        }
    }
}

实战应用

在这段代码中,创建了一个简单的图书馆管理系统,使用了索引器重载以及LINQ的特性,提供了一种高效且直观的方式来管理和查询书籍信息。

using System;
using System.Collections.Generic;

public class Library
{
    private List<string> bookTitles = new List<string>();
    private List<string> authors = new List<string>();
    private int[] stockCounts;
    private int[] publicationYears;
    private string[] isbnNumbers;

    // 构造函数
    public Library(int capacity)
    {
        stockCounts = new int[capacity];
        publicationYears = new int[capacity];
        isbnNumbers = new string[capacity];
    }

    // 方法:添加书籍
    public void AddBook(string title, string author, int stock, int publicationYear, string isbn)
    {
        bookTitles.Add(title);
        authors.Add(author);
        int index = bookTitles.Count - 1; // 新书的索引
        stockCounts[index] = stock; // 设置库存
        publicationYears[index] = publicationYear; // 设置出版年份
        isbnNumbers[index] = isbn; // 设置ISBN
    }

    // 索引器:根据书名获取库存数量
    public int this[string title]
    {
        get 
        {
            int index = bookTitles.IndexOf(title);
            return index != -1 ? stockCounts[index] : 0; // 如果不存在,返回0
        }
        set 
        {
            int index = bookTitles.IndexOf(title);
            if (index != -1)
            {
                stockCounts[index] = value;
            }
        }
    }

    // 索引器:根据书名获取出版年份
    public int this[string title, string infoType]
    {
        get 
        {
            int index = bookTitles.IndexOf(title);
            if (index == -1) return 0; // 如果书名不存在,返回0

            return infoType.ToLower() == "year" ? publicationYears[index] : 0;
        }
    }

    // 索引器:根据书名获取ISBN号
    public string this[string title, int infoType]
    {
        get 
        {
            int index = bookTitles.IndexOf(title);
            return index != -1 ? isbnNumbers[index] : null; // 如果书名不存在,返回null
        }
    }

    // 方法:显示所有书籍信息
    public void DisplayBooks()
    {
        for (int i = 0; i < bookTitles.Count; i++)
        {
            Console.WriteLine($"书名: {bookTitles[i]}, 作者: {authors[i]}, 库存: {stockCounts[i]}, 出版年份: {publicationYears[i]}, ISBN: {isbnNumbers[i]}");
        }
    }
}

    // 方法:根据作者查询书籍----使用LINQ和索引器
    public IEnumerable<string> GetBooksByAuthor(string author)
    {
        return bookTitles.Where((title, index) => authors[index] == author).ToList();
    }

    // 方法:获取库存少于特定数量的书籍----使用LINQ和索引器
    public IEnumerable<string> GetBooksWithLowStock(int threshold)
    {
        return bookTitles.Where((title, index) => stockCounts[index] < threshold).ToList();
    }

public class Program
{
    public static void Main()
    {
        Library library = new Library(10); // 创建一个容量为10的图书馆
        
        // 添加书籍
        library.AddBook("C#编程", "Tdm888", 5, 2020, "978-3-16-148410-0");
        library.AddBook("数据结构与算法", "李四", 4, 2021, "978-0-123-45678-9");
        library.AddBook("设计模式", "王五", 2, 2018, "978-1-234-98765-4");
        library.AddBook("C#高级编程", "赵六", 6, 2022, "978-3-16-987654-0");

        // 显示所有书籍信息
        library.DisplayBooks();
        Console.WriteLine();

        // 多次访问库存、出版年份和ISBN
        Console.WriteLine($"《C#编程》的库存: {library["C#编程"]}");
        Console.WriteLine($"《C#编程》的出版年份: {library["C#编程", "year"]}");
        Console.WriteLine($"《C#编程》的ISBN: {library["C#编程", 1]}");

        Console.WriteLine();

        Console.WriteLine($"《设计模式》的库存: {library["设计模式"]}");
        Console.WriteLine($"《设计模式》的出版年份: {library["设计模式", "year"]}");
        Console.WriteLine($"《设计模式》的ISBN: {library["设计模式", 1]}");
        Console.WriteLine();
        // 根据作者查找书籍
        var booksByAuthor = library.GetBooksByAuthor("李四");
        Console.WriteLine("李四的书籍:");
        foreach (var title in booksByAuthor)
        {
            Console.WriteLine(title);
        }

        Console.WriteLine();

        // 查找库存少于3的书籍
        var lowStockBooks = library.GetBooksWithLowStock(3);
        Console.WriteLine("库存少于3的书籍:");
        foreach (var title in lowStockBooks)
        {
            Console.WriteLine(title);
        }
    }
}
书名: C#编程, 作者: Tdm888, 库存: 5, 出版年份: 2020, ISBN: 978-3-16-148410-0
书名: 数据结构与算法, 作者: 李四, 库存: 4, 出版年份: 2021, ISBN: 978-0-123-45678-9
书名: 设计模式, 作者: 王五, 库存: 2, 出版年份: 2018, ISBN: 978-1-234-98765-4
书名: C#高级编程, 作者: 赵六, 库存: 6, 出版年份: 2022, ISBN: 978-3-16-987654-0

《C#编程》的库存: 5
《C#编程》的出版年份: 2020
《C#编程》的ISBN: 978-3-16-148410-0

《设计模式》的库存: 2
《设计模式》的出版年份: 2018
《设计模式》的ISBN: 978-1-234-98765-4

李四的书籍:
数据结构与算法

库存少于3的书籍:
设计模式

索引器

  • 第一个索引器this[string title]允许通过书名直接获取库存数量。如果书名不存在,则返回0。这个索引器也支持设置库存数量。
  • 第二个索引器this[string title, string infoType]获取出版年份。通过检查infoType的值,并使用书名查找对应的出版年份,若书名不存在则返回0。
  • 第三个索引器this[string title, int infoType]用于获取ISBN号,类似地,通过书名查找对应的ISBN。如果书名不存在则返回null。

LINQ的使用:

  • GetBooksByAuthor(string author):该方法使用LINQ的Where函数,根据给定的作者筛选出所有书籍的标题。内部实现是通过访问authors列表来获取每本书对应的作者,从而判断是否匹配。
  • GetBooksWithLowStock(int threshold):这个方法同样运用LINQ的Where函数,筛选出库存低于指定阈值的书籍。使用索引器的特性,可以直接通过索引访问库存数组,为每本书进行有效性检查。