• 因为不同的键,可能返回相同的散列代码值,所以需要用Equals()方法来比较键, A.Equals(B)
  • 必须始终确保如下条件成立: 如果 A.Equals(B) 为true, 那么 A.GetHashCode()和B.GetHashCode() 总是返回相同的散列代码值。这个条件成立很重要,如果用作键的类型不满足此条件,字典就不能正常工作,会发生有趣的事情,例如放进字典后就再也检索不到它,或者检索得到错误的项。
  • System.Object 作为字典的键

  • Equals(),比较引用
  • GetHashCode(), 返回一个基于对象地址的散列代码值
  • 类实例 作为key,而放入字典的value时, 类实例的引用 和value建立了一一对应的关系, 若想检索value , 就必须保存着类实例的引用, 这不太方便 要想方便 ,这个类需要重写 Equals() GetHashCode()

    System.String 作为字典的键

  • 实现了 IEquatable 接口, Equals() 比较值
  • GetHashCode() ,返回一个基于字符串值的散列代码值
  • System.String 作为字典的键,很方便
  • Int32 作为字典的键

  • 实现了 IEquatable 接口
  • GetHashCode()
  • Int32 作为键,其 散列代码值 可能 没有平均分布 在int.MinValue和int.MaxValue之间,因此,不能获得 最佳性能 因此,Int32不太适合作为键
  • 如果 键类型 没有实现 IEquatable 接口,也没有重写 GetHashCode() 方法

  • Dictionary<TKey, TValue> 构造函数的重载版本,接收一个 IEqualityComparer<T>
  • IEqualityComparer<T> 定义了 GetHashCode() Equals()
  •     public class Employee
            private readonly string _name;
            private readonly decimal _salary;
            private readonly EmployeeId _id;
            public Employee(EmployeeId id, string name, decimal salary)
                _id = id;
                _name = name;
                _salary = salary;
            public override string ToString() => $"{_id.ToString()}: {_name, -20} {_salary :C}";
    
        public class EmployeeIdException : Exception
            public EmployeeIdException(string message) : base(message) { }
        public struct EmployeeId : IEquatable<EmployeeId>
            private readonly char _prefix;
            private readonly int _number;
            public EmployeeId(string id)
                if (id == null) throw new ArgumentNullException(nameof(id));
                _prefix = (id.ToUpper())[0];
                int numLength = id.Length - 1;
                    _number = int.Parse(id.Substring(1, numLength > 6 ? 6 : numLength));
                catch (FormatException)
                    throw new EmployeeIdException("Invalid EmployeeId format");
            public override string ToString() => _prefix.ToString() + $"{_number,6:000000}";
            public override int GetHashCode() => (_number ^ _number << 16) * 0x1505_1505;
            public bool Equals(EmployeeId other) => _prefix == other._prefix && _number == other._number;
            public override bool Equals(object obj) => Equals((EmployeeId)obj);
            public static bool operator ==(EmployeeId left, EmployeeId right) => left.Equals(right);
            public static bool operator !=(EmployeeId left, EmployeeId right) => !(left == right);
    
        class Program
            static void Main()
                var idJimmie = new EmployeeId("C48");
                var jimmie = new Employee(idJimmie, "Jimmie Johnson", 150926.00m);
                var idJoey = new EmployeeId("F22");
                var joey = new Employee(idJoey, "Joey Logano", 45125.00m);
                var idKyle = new EmployeeId("T18");
                var kyle = new Employee(idKyle, "Kyle Bush", 78728.00m);
                var idCarl = new EmployeeId("T19");
                var carl = new Employee(idCarl, "Carl Edwards", 80473.00m);
                var idMatt = new EmployeeId("T20");
                var matt = new Employee(idMatt, "Matt Kenseth", 113970.00m);
                var employees = new Dictionary<EmployeeId, Employee>(31)
                    [idJimmie] = jimmie,
                    [idJoey] = joey,
                    [idKyle] = kyle,
                    [idCarl] = carl,
                    [idMatt] = matt
                foreach (var employee in employees.Values)
                    Console.WriteLine(employee);
                while (true)
                    Console.Write("Enter employee id (X to exit)> ");
                    var userInput = Console.ReadLine();
                    userInput = userInput.ToUpper();
                    if (userInput == "X") break;
                    EmployeeId id;
                        id = new EmployeeId(userInput);
                        if (!employees.TryGetValue(id, out Employee employee))
                            Console.WriteLine($"Employee with id {id} does not exist");
                            Console.WriteLine(employee);
                    catch (EmployeeIdException ex)
                        Console.WriteLine(ex.Message);
    

    输出:(存入字典的数据项都能用键给检索出来)

    C000048: Jimmie Johnson150,926.00
    F000022: Joey Logano45,125.00
    T000018: Kyle Bush78,728.00
    T000019: Carl Edwards80,473.00
    T000020: Matt Kenseth113,970.00
    Enter employee id (X to exit)> T19
    T000019: Carl Edwards80,473.00
    Enter employee id (X to exit)> 148
    Employee with id 1000048 does not exist
    Enter employee id (X to exit)> T48
    Employee with id T000048 does not exist
    Enter employee id (X to exit)> C48
    C000048: Jimmie Johnson150,926.00
    Enter employee id (X to exit)> F22
    F000022: Joey Logano45,125.00
    Enter employee id (X to exit)>
    复制代码
    分类:
    后端
    标签: