Dictionary.ContainsKey始终返回False

Rom*_*key 9 c# dictionary

好吧,我正在尝试创建一个小应用程序,以节省一些员工姓名,年龄和工资.所以我决定用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); 
Run Code Online (Sandbox Code Playgroud)

员工类

public class Employee
{
    public string Name { get; set; }
    public int Age { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然而,当我评论或作为主题标题陈述时,.ContainsKey总是返回我,False虽然我尝试了两种方式,如代码中所示.

Pat*_*iek 18

您没有使用接收的Dictionary构造函数,IEqualityComparer<T>也没有在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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后:

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!
Run Code Online (Sandbox Code Playgroud)

为了完整,这里只有名称比较器(也是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);
        }
  }
Run Code Online (Sandbox Code Playgroud)

但是,正如您所注意到的,您必须决定在创建字典时将使用哪个比较器进行键比较.以后不能改变......

  • @AlexFilipovici这是由ReSharper生成的,潜在的原因是[这里](http://stackoverflow.com/a/102878/1180426).其他优秀的哈希码实现,比这个更容易记住,是来自'Effective Java'的 - 我见过Jon Skeet在这里和那里使用它... (2认同)