Well i am trying to create a small application that saves some employees Names, Ages as well as salaries. So i decided to use Dictionary
in order to set every employee's salary and i came up with that code
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; }
}
However as i commented out or as the topic title states, .ContainsKey
always returns me False
although i tried both ways as shown in the code.
Syntax: public bool ContainsKey (TKey key); Here, the key is the Key which is to be located in the Dictionary. Return Value: This method will return true if the Dictionary contains an element with the specified key otherwise, it returns false.
Dictionary is not Thread-Safe.
Remarks. The key is handled in a case-insensitive manner; it is translated to lowercase before it is used.
TryGetValue Method: This method combines the functionality of the ContainsKey method and the Item property. If the key is not found, then the value parameter gets the appropriate default value for the value type TValue; for example, 0 (zero) for integer types, false for Boolean types, and null for reference types.
You're not using the Dictionary
constructor that takes in the IEqualityComparer<T>
and neither have you implemented custom equality on the Employee
class.
So right now the dictionary is comparing employees by reference. When you new
an employee, you have a different reference, even though e.g. name might be the same.
Probably the easiest way here would be to implement your own IEqualityComparer<Employee>
, where you could pick which members will be used for equality comparison, and pass it to the dictionary's constructor.
[EDIT] As promised, snippets:
//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;
}
}
}
And then:
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!
For completeness, here's name-only comparer (also ReSharper's courtesy):
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);
}
}
But, as you noticed, you have to decide which comparer you will use for key-comparison when you create a dictionary. That can't be changed later on...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With