QYYEE 5 лет назад
Родитель
Сommit
278610065e
1 измененных файлов: 142 добавлений и 0 удалений
  1. 142
    0
      实践/后端/C#基础/26.字典.md

+ 142
- 0
实践/后端/C#基础/26.字典.md Просмотреть файл

@@ -0,0 +1,142 @@
1
+> 字典
2
+- 字典表示一种非常复杂的数据结构,这种数据结构允许按照某个键来访问元素,字典也称为映射或散列表。
3
+- 字典的主要特性是能根据键快速查找值。也可以自由添加和删除元素,这有点像List<T>类,但没有在内存中移动后续元素的性能开销。
4
+
5
+
6
+**键的类型**
7
+
8
+- 用作字典中的键的类型必须重写Object类的GetHashCode()方法。只要字典类需要确定元素的位置,它就要调用GetHashCode()方法。
9
+- GetHashCode()方法的实现代码必须满足如下要求:
10
+    - 相同的对象应总是返回相同的值。
11
+    - 不同的对象可以返回相同的值。
12
+    - 它不能抛出异常。
13
+    - 它应至少使用一个实例字段。
14
+    - 散列代码最好在对象的生存期中不发生变化。
15
+    - 它应执行的比较快,计算的开销不大
16
+    - 散列代码值应平均分布在int可以存储的整个数字范围上。
17
+
18
+
19
+> 字典示例
20
+
21
+- 字典示例程序建立一个员工字典。该字典用EmployeeId对象来索引,储存在字典中的每个数据项都是一个Employee对象,该对象存储员工的详细数据。
22
+```
23
+public class EmployeeIdException:Exception
24
+{
25
+    public EmployeeIdException(string message):base(message){}
26
+}
27
+public truct EmployeeId:IEquatable<EmployeeId>
28
+{
29
+    private readonly char _prefix;
30
+    private readonly int _number;
31
+    
32
+    public EmployeeId(string id)
33
+    {
34
+        Contract.Requires<ArgumentNullException>(id!=null);
35
+
36
+        _prefix=(id.ToUpper())[0];
37
+        int numLength=id.Length-1;
38
+        try
39
+        {
40
+            _number=int.Parse(id.Substring(1,numLength>6?6:numLength));
41
+        }
42
+        catch (FormatException)
43
+        {
44
+            throw new EmployeeIdException("Invalid EmployeeId format");
45
+        }
46
+    }
47
+    public override string ToString()=>_prefix.ToString()+$"{number,6:000000}";
48
+    public override int GetHashCode()=>(number^number<<16)*0x15051505;
49
+    public bool Equals(EmployeeId other)=>(prefix==other?.prefix && number == other?.number);
50
+    public override bool Equals(object obj)=>Equals((EmployeeId)obj);
51
+
52
+    public static bool operator ==(EmployeeId left,EmployeeId right)=>left.Equals(right);
53
+
54
+    public static bool operator !=(EmployeeId left,EmployeeId right)=>!(left==right);
55
+
56
+}
57
+```
58
+- 由IEquatable<T>接口定义的Equals()方法比较两个EmployeeId对象的值,如果这两个值相同,它就返回true。除了实现IEquatable<T>接口中的Equals()方法之外,还可以重写Object类中的Equals()方法。
59
+
60
+- Employee类是一个简单的实体类,该实体类包含员工的姓名、薪水和ID。构造函数初始化所有值,ToString()方法返回一个实例的字符串表示。ToString()方法的实现代码使用格式化字符串创建字符串表示,以提高性能
61
+
62
+```
63
+public class Employee
64
+{
65
+    private string _name;
66
+    private decimal _salary;
67
+    private readonly EmployeeId _id;
68
+
69
+    public Employee (EmployeeId id,string name,decimal salary)
70
+    {
71
+        _id=id;
72
+        _name=name;
73
+        _salary=salary;
74
+    }
75
+    public override string ToString()=>$"{id.ToString()}:{name,-20} {salary:C}";
76
+}
77
+```
78
+- 示例应用程序的Main()方法中,创建一个新的Dictionary<TKey,TValue>实例,其中键是EmployeeId类型,值是Employee类型。构造函数指定31个元素的容量。注意容量一般是素数。但如果指定了一个不是素数的值,也不需要担心。Dictionary<TKey,Tvalue>类会使用传递给构造函数的整数后面紧接着的一个素数来指定容量。创建员工对象和ID后,就使用新的字典初始化语法把它们添加到新建的字典中
79
+
80
+```
81
+public static void Main()
82
+{
83
+    var employees=new Dictionary<EmployeeId,Employee>(31);
84
+    var idTony =new EmployeeId("c3755");
85
+    var tony =new Employee(idTony,"Tony Stewart",379025.00m);
86
+
87
+    var idCarl=new EmployeeId("F3547");
88
+    var carl=new Employee(idCarl,"Carl Edwards",403466.00m);
89
+
90
+    var idKevin=new EmployeeId("c3386");
91
+    var kevin=new Employee(idKevin,"Kevin Harwick",415261.00m);
92
+
93
+    var idMatt=new EmployeeID("F3323");
94
+    var matt=new Employee(idMatt,"Matt Kenseth",1589390.00m);
95
+
96
+    var idBrad=new EmployeeId("D3234");
97
+    var brad=new Employee(idBrad,"Brad Keselowski",322295.00m);
98
+
99
+    var employees=new Dictionary<EmployeeId,Employee>(31)
100
+    {
101
+        [idTony]=tony,
102
+        [idCarl]=carl,
103
+        [idKevin]=kevin,
104
+        [idMatt]=matt,
105
+        [idBrad]=brad
106
+    };
107
+    foreach(var employee inemployee.Values)
108
+    {
109
+        WriteLine(employee);
110
+    }
111
+}
112
+```
113
+```
114
+while (true)
115
+{
116
+    Write("Enter employee id(X to exit)");
117
+    var userInput=ReadLine();
118
+    userInput=userInput.ToUpper();
119
+    if(userInput == "X") break;
120
+
121
+    EmployeeId id;
122
+    try
123
+    {
124
+        id=new EmployeeId(userInput);
125
+
126
+        Employee employee;
127
+        if(!employee.TryGetValue(id,out employee))
128
+        {
129
+            WriteLine($"Employee with id{id} does not exist");
130
+
131
+        }
132
+        else
133
+        {
134
+            WriteLine(employee);
135
+        }
136
+    }
137
+    catch(EmployeeIdException ex)
138
+    {
139
+        WriteLine(ex.Message);
140
+    }
141
+}
142
+```

Загрузка…
Отмена
Сохранить