Dictionary.ContainsKey总是返回False

本文关键字:返回 False ContainsKey Dictionary | 更新日期: 2023-09-27 18:22:06

我正在尝试创建一个小型应用程序,它可以保存一些员工的姓名、年龄和工资。因此,我决定使用Dictionary来设置每个员工的工资,并想出了代码

代码

var employeeSalaryDictionary = new Dictionary<Employee, int>();
employeeSalaryDictionary.Add(new Employee { Name = "Chuck", Age = 37 }, 1000);
employeeSalaryDictionary.Add(new Employee { Name = "Norris", Age = 37 }, 2000);
employeeSalaryDictionary.Add(new Employee { Name = "Rocks", Age = 44 }, 3000);
Employee employeeToFind = new Employee { Name = "Chuck", Age = 37 };
//or even
Employee employeeToFind = new Employee { Name = "Chuck"};
//Always False...
bool exists = employeeSalaryDictionary.ContainsKey(employeeToFind); 

员工类别

public class Employee
{
    public string Name { get; set; }
    public int Age { get; set; }
}

但是当我注释掉或主题标题中指出,.ContainsKey总是返回False,尽管我尝试了两种方法,如代码中所示。

Dictionary.ContainsKey总是返回False

您没有使用接受IEqualityComparer<T>Dictionary构造函数,也没有在Employee类上实现自定义相等。

因此,现在字典正在通过引用对员工进行比较。当您new是一名员工时,您有一个不同的引用,即使例如名称可能相同。

这里最简单的方法可能是实现您自己的IEqualityComparer<Employee>,在那里您可以选择哪些成员将用于相等性比较,并将其传递给字典的构造函数。

[编辑]如承诺,片段:

//ReSharper's courtesy
public sealed class NameAgeEqualityComparer : IEqualityComparer<Employee>
{
    public bool Equals(Employee x, Employee y)
    {
        if (ReferenceEquals(x, y)) return true;
        if (ReferenceEquals(x, null)) return false;
        if (ReferenceEquals(y, null)) return false;
        if (x.GetType() != y.GetType()) return false;
        return string.Equals(x.Name, y.Name) && x.Age == y.Age;
    }
    public int GetHashCode(Employee obj)
    {
        unchecked
        {
            return ((obj.Name != null ? obj.Name.GetHashCode() : 0) * 397) ^ obj.Age;
        }
    }
}

然后:

var employeeSalaryDictionary = new Dictionary<Employee, int>(new NameAgeEqualityComparer());
employeeSalaryDictionary.Add(new Employee { Name = "Chuck", Age = 37 }, 1000);
employeeSalaryDictionary.Add(new Employee { Name = "Norris", Age = 37 }, 2000);
employeeSalaryDictionary.Add(new Employee { Name = "Rocks", Age = 44 }, 3000);
Employee employeeToFind = new Employee { Name = "Chuck", Age = 37 };
bool exists = employeeSalaryDictionary.ContainsKey(employeeToFind); // true!

为了完整起见,这里有一个仅限名字的比较器(也是ReSharper提供的):

 public sealed class NameEqualityComparer : IEqualityComparer<Employee>
 {
        public bool Equals(Employee x, Employee y)
        {
            if (ReferenceEquals(x, y)) return true;
            if (ReferenceEquals(x, null)) return false;
            if (ReferenceEquals(y, null)) return false;
            if (x.GetType() != y.GetType()) return false;
            return string.Equals(x.Name, y.Name);
        }
        public int GetHashCode(Employee obj)
        {
            return (obj.Name != null ? obj.Name.GetHashCode() : 0);
        }
  }

但是,正如您所注意到的,在创建字典时,您必须决定使用哪个比较器进行关键字比较。以后无法更改…

Employee是一个引用类型。添加新员工时,字典关键字将包含该employee对象的引用地址。如果您创建另一个Employee对象,它与您的第一个Employer对象具有不同的引用,即使它们包含相同的数据