我正在尝试创建一个小型应用程序,以节省一些员工姓名,年龄和工资。所以我决定使用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
,尽管我尝试了两种方法,如代码中所示。
答案 0 :(得分:18)
您没有使用Dictionary
的{{1}}构造函数,也没有在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;
}
}
}
为了完整性,这里是仅限名称的比较器(也是ReSharper的礼貌):
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!
但是,正如您所注意到的,您必须决定在创建字典时将使用哪个比较器进行键比较。以后不能改变......
答案 1 :(得分:3)
员工是一种参考类型。添加新员工时,您的字典键将包含该Employee对象的引用地址。如果您创建另一个Employee对象,则它具有与第一个Employee对象不同的引用,即使它们包含相同的数据