首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 索引器實作指南(一):自訂集合類別、IEnumerator 介面、雙重索引鍵 (整數/字串) 完整範例

     編輯:關於C語言

為什麼需要自訂索引器?

雖然 List<T>、Dictionary<K,V> 已足夠強大,但自訂索引器可:

  • 同時支援**整數索引**與**字串鍵值**雙重存取
  • 封裝商業邏輯 (驗證、事件通知、延遲載入)
  • 實作 IEnumerable 支援 foreach
  • 控制容量上限、重複鍵處理策略

完整 Employees 容器類別

using 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 為識別碼,不應透過索引器修改

現代化改良 (C# 2.0+ 泛型)

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();
}

索引器設計原則

  1. 語意直觀:this[key] 對應單一邏輯實體
  2. 效能預期:O(1) 或 O(log n);字串查找 O(n) 需文件化
  3. 邊界處理:回傳 null 或拋出 IndexOutOfRangeException 二擇一,保持一致
  4. 不可變性:唯讀集合只提供 get
  5. 文件化:XML 註解說明鍵的格式、範圍、大小寫敏感度
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved