索引器 是 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}");
}
}
不适用索引器的情况下,通过 Get
和 Set
方法来访问和修改集合中的元素。
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
函数,筛选出库存低于指定阈值的书籍。使用索引器的特性,可以直接通过索引访问库存数组,为每本书进行有效性检查。