字典Dictionary

在 C# 中使用 Dictionary<TKey, TValue> 时,需要注意以下几点:

  1. 键的唯一性

    • 字典中的每个键必须是唯一的。如果尝试添加一个已经存在的键,会抛出 ArgumentException
      1
      2
      3
      var dict = new Dictionary<int, string>();
      dict.Add(1, "value1");
      dict.Add(1, "value2"); // 抛出 ArgumentException
  2. 键的哈希码和相等性

    • 键的类型必须正确实现 GetHashCodeEquals 方法。如果键的类型是一个自定义类,确保正确实现这两个方法,以便字典能够正确区分键。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      public class Key
      {
      public int Id { get; set; }
      public override bool Equals(object obj)
      {
      if (obj is Key key)
      return Id == key.Id;
      return false;
      }

      public override int GetHashCode()
      {
      return Id.GetHashCode();
      }
      }
  3. 性能考虑

    • 字典查找、添加和删除操作的时间复杂度平均为 O(1),但在哈希冲突较多的情况下可能退化到 O(n)。选择合适的键类型和哈希函数以减少冲突。
  4. 访问不存在的键

    • 直接访问一个不存在的键会抛出 KeyNotFoundException。可以使用 TryGetValue 方法避免异常。
      1
      2
      3
      4
      5
      6
      7
      8
      if (dict.TryGetValue(2, out var value))
      {
      Console.WriteLine(value);
      }
      else
      {
      Console.WriteLine("Key not found");
      }
  5. 初始化容量

    • 如果知道字典的大致大小,可以在初始化时指定容量,减少扩容带来的性能开销。
      1
      var dict = new Dictionary<int, string>(capacity: 100);
  6. 线程安全

    • Dictionary<TKey, TValue> 本身不是线程安全的。如果在多线程环境中使用,请使用 ConcurrentDictionary<TKey, TValue> 或手动实现同步机制。
  7. 迭代和修改

    • 在迭代字典时修改字典会抛出 InvalidOperationException。如果需要修改,可以先收集要修改的键值对,然后在迭代完成后再进行修改。
      1
      2
      3
      4
      5
      6
      7
      foreach (var key in dict.Keys.ToList())
      {
      if (key == 1)
      {
      dict[key] = "newValue";
      }
      }
  8. 序列化

    • 字典可以被序列化,但要确保键和值的类型都支持序列化。常用的 JSON 序列化库如 JsonConvertSystem.Text.Json 都支持字典。
      1
      2
      var json = JsonConvert.SerializeObject(dict);
      var deserializedDict = JsonConvert.DeserializeObject<Dictionary<int, string>>(json);

示例代码

这段示例代码展示了如何正确使用字典以及注意事项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using System;
using System.Collections.Generic;

public class Example
{
public static void Main()
{
var dict = new Dictionary<int, string>();

// 添加元素
dict.Add(1, "value1");
dict[2] = "value2"; // 另一种添加方式

// 访问元素
if (dict.TryGetValue(1, out var value))
{
Console.WriteLine(value); // 输出: value1
}

// 遍历字典
foreach (var kvp in dict)
{
Console.WriteLine($"Key: {kvp.Key}, Value: {kvp.Value}");
}

// 删除元素
dict.Remove(1);

// 检查键是否存在
if (!dict.ContainsKey(1))
{
Console.WriteLine("Key 1 not found");
}

// 键的自定义类
var customDict = new Dictionary<Key, string>();
var key1 = new Key { Id = 1 };
customDict[key1] = "customValue1";
Console.WriteLine(customDict[key1]); // 输出: customValue1
}
}

public class Key
{
public int Id { get; set; }
public override bool Equals(object obj)
{
if (obj is Key key)
return Id == key.Id;
return false;
}

public override int GetHashCode()
{
return Id.GetHashCode();
}
}

字典Dictionary
https://newztx.github.io/2024/07/24/字典Dictionary/
作者
Cranky Dove
发布于
2024年7月24日
许可协议