雖然 List<T>、Dictionary<K,V> 已足夠強大,但自訂索引器可:
IEnumerable 支援 foreachusing System;
using System.Collections;
public class Employees : IEnumerable // 實作 IEnumerable 支援 foreach
{
private readonly ArrayList _list;
private readonly int _maxCount;
public Employees(int maxCount)
{
_maxCount = maxCount;
_list = new ArrayList(maxCount);
}
// ===== 整數索引器 =====
public Employee this[int index]
{
get
{
if (index < 0 || index >= _list.Count) return null;
return (Employee)_list[index];
}
set
{
if (index < 0 || index >= _maxCount) return;
if (index >= _list.Count)
_list.Add(value); // 擴展
else
_list[index] = value; // 覆寫
}
}
// ===== 字串索引器 (SSN 查找) =====
public Employee this[string ssn]
{
get
{
if (string.IsNullOrEmpty(ssn)) return null;
foreach (Employee emp in _list)
if (emp?.SSN == ssn) return emp;
return null;
}
// 字串索引器通常唯讀,不提供 set
}
public int Count => _list.Count;
public int Capacity => _maxCount;
// ===== IEnumerable 實作 =====
public IEnumerator GetEnumerator() => _list.GetEnumerator();
// 額外:支援移除
public void RemoveAt(int index)
{
if (index >= 0 && index < _list.Count)
_list.RemoveAt(index);
}
public void Remove(string ssn)
{
for (int i = _list.Count - 1; i >= 0; i--)
if (((Employee)_list[i])?.SSN == ssn)
_list.RemoveAt(i);
}
}
var emps = new Employees(10);
// 新增
emps[0] = new Employee("王", "小", "明", "A123456789");
emps[1] = new Employee("李", "", "華", "B987654321");
// 整數索引存取
Console.WriteLine(emps[0]?.FirstName); // 王
// 字串索引存取
var emp = emps["B987654321"];
Console.WriteLine(emp?.LastName); // 華
// foreach 列舉
foreach (Employee e in emps)
Console.WriteLine(e);
// 移除
emps.Remove("A123456789");
Console.WriteLine($"剩餘:{emps.Count}");
| 細節 | 說明 |
|---|---|
| 繼承 IEnumerable | 僅需實作 GetEnumerator(),編譯器自動支援 foreach |
| ArrayList 內部儲存 | 示範用;實務建議用 List<Employee> 避免裝箱 |
| 索引器 get 回傳 null | 索引越界或查無資料時回傳 null,避免拋出例外 |
| 索引器 set 擴展行為 | 索引 >= Count 視為新增,否則覆寫 |
| 字串索引器唯讀 | SSN 為識別碼,不應透過索引器修改 |
public class EmployeeCollection : IEnumerable
{
private readonly List _list = new();
private readonly int _maxCount;
public EmployeeCollection(int maxCount) => _maxCount = maxCount;
public Employee this[int index]
{
get => (index >= 0 && index < _list.Count) ? _list[index] : null;
set
{
if (index < 0 || index >= _maxCount) return;
if (index >= _list.Count) _list.Add(value);
else _list[index] = value;
}
}
public Employee this[string ssn] =>
_list.FirstOrDefault(e => e?.SSN == ssn);
public int Count => _list.Count;
public IEnumerator GetEnumerator() => _list.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
this[key] 對應單一邏輯實體IndexOutOfRangeException 二擇一,保持一致