1. 封装和隐藏内部实现
数组是一个简单的数据结构,它的内部实现是固定的(基于连续内存)。而索引器可以隐藏内部的实现细节,允许开发者使用更复杂的数据结构来存储数据,同时对外提供类似数组的访问方式。
示例:
假设你有一个类,内部使用 Dictionary
或 List
来存储数据,但你希望用户可以通过索引访问这些数据,就像访问数组一样。索引器可以实现这种封装。
csharp复制
public class MyCollection
{private Dictionary<int, string> _data = new Dictionary<int, string>();public string this[int index]{get => _data.ContainsKey(index) ? _data[index] : null;set => _data[index] = value;}
}
在这个例子中,用户可以通过索引访问数据,但内部实现是基于字典的,而不是数组。
2. 提供更灵活的访问方式
索引器可以支持多种参数类型和多个参数,而数组的索引只能是整数。这使得索引器可以实现更复杂的访问逻辑。
示例:
假设你有一个二维矩阵,但内部存储方式是基于一维数组的。通过索引器,你可以提供二维索引的访问方式,而内部逻辑可以将二维索引转换为一维索引。
csharp复制
public class Matrix
{private int[] _data = new int[25]; // 5x5 矩阵存储在一维数组中public int this[int row, int col]{get => _data[row * 5 + col];set => _data[row * 5 + col] = value;}
}
3. 支持自定义逻辑
索引器可以在 get
和 set
访问器中添加自定义逻辑,比如参数验证、日志记录、数据转换等。数组则无法实现这些功能。
示例:
在设置值时验证数据是否合法。
csharp复制
public class MyCollection
{private List<int> _data = new List<int>();public int this[int index]{get => _data[index];set{if (value < 0){throw new ArgumentException("值不能为负数");}_data[index] = value;}}
}
4. 实现类似数组的接口
索引器可以用于实现类似数组的接口,但内部实现可以是任意类型。例如,你可以实现一个类似数组的集合,但内部使用链表或其他数据结构。
示例:
实现一个类似数组的集合,但内部使用链表。
csharp复制
public class LinkedListArray
{private LinkedList<int> _list = new LinkedList<int>();public int this[int index]{get{if (index < 0 || index >= _list.Count)throw new IndexOutOfRangeException();var current = _list.First;for (int i = 0; i < index; i++){current = current.Next;}return current.Value;}set{if (index < 0 || index >= _list.Count)throw new IndexOutOfRangeException();var current = _list.First;for (int i = 0; i < index; i++){current = current.Next;}current.Value = value;}}
}
5. 支持更复杂的键值对访问
索引器可以接受任意类型的参数,而不仅仅是整数。这使得它非常适合实现类似字典的功能,但提供更直观的访问方式。
示例:
实现一个类似字典的类,但通过索引器访问。
csharp复制
public class MyDictionary
{private Dictionary<string, int> _data = new Dictionary<string, int>();public int this[string key]{get => _data[key];set => _data[key] = value;}
}