System.Collections.Hashtable 是非泛型鍵值對集合,鍵值皆為 object。特點:
Synchronized 包裝)Dictionary<TKey, TValue>(泛型、型別安全、效能更佳)using System.Collections;
var ht = new Hashtable();
// 新增 / 更新
ht.Add("E", "e"); // 鍵不存在才能加
ht["A"] = "a"; // 索引器:不存在則加,存在則更新
ht["C"] = "c";
ht["B"] = "b";
// 讀取
string val = (string)ht["A"]; // 需轉型
Console.WriteLine(val); // a
// 存在性檢查
if (ht.ContainsKey("E")) Console.WriteLine("Key E 存在");
if (ht.ContainsValue("x")) Console.WriteLine("Value x 存在");
// 移除
ht.Remove("C"); // 移除指定鍵
ht.Clear(); // 清空所有
// 計數
Console.WriteLine(ht.Count);
// 方式一:DictionaryEntry(舊式,需轉型)
foreach (DictionaryEntry de in ht)
{
Console.WriteLine($"Key={de.Key}, Value={de.Value}");
}
// 方式二:Keys 集合 + 索引器
foreach (string key in ht.Keys)
{
Console.WriteLine($"Key={key}, Value={ht[key]}");
}
// 方式三:Values 集合(僅需值)
foreach (string value in ht.Values)
{
Console.WriteLine(value);
}
Hashtable 本身無序,若需排序輸出,需將 Keys 複製到可排序結構。
// 字母排序鍵
var keys = new ArrayList(ht.Keys);
keys.Sort(); // 或 keys.Sort(StringComparer.OrdinalIgnoreCase)
foreach (string key in keys)
{
Console.WriteLine($"{key}:{ht[key]}");
}
// 輸出範例:
// A:a
// B:b
// E:e
var htIgnoreCase = new Hashtable(StringComparer.OrdinalIgnoreCase);
htIgnoreCase["Key"] = 1;
htIgnoreCase["key"] = 2; // 會覆蓋上一筆
Console.WriteLine(htIgnoreCase.Count); // 1
var syncHt = Hashtable.Synchronized(new Hashtable());
// 多執行緒環境下直接操作 syncHt
// 但枚舉時仍需手動鎖定:
lock (syncHt.SyncRoot)
{
foreach (DictionaryEntry de in syncHt) { /* ... */ }
}
new Hashtable(1000) 減少重新雜湊new Hashtable(1000, 0.7f)(預設 1.0,較低可減少碰撞但佔更多記憶體)| 特性 | Hashtable | Dictionary<TKey, TValue> |
|---|---|---|
| 型別安全 | 否(object) | 是(泛型) |
| 效能 | 需裝箱/拆箱 | 無裝箱,更快 |
| Null 鍵 | 不允許 | 允許(參考型別) |
| 枚舉順序 | 無序 | 無序(但 .NET 6+ 保持插入順序) |
| 執行緒安全 | 靜態 Synchronized | 無內建,需自行實作 |
| 適用場景 | 舊版相容、動態型別、非泛型 API | 現代 .NET 專案首選 |
Hashtable 是 .NET 1.0 時代的產物,理解其運作原理有助於維護舊系統;新開發專案請優先使用 Dictionary<TKey, TValue>,享受型別安全、更佳效能與豐富 API(如 TryGetValue、GetValueOrDefault)。若需有序字典,可考慮 SortedDictionary、SortedList 或 .NET 6+ 的 OrderedDictionary。