namespace Dic
{
public class Key
{
string name;
public Key(string n) { name = n; }
}
class Program
{
static string Test()
{
Key a = new Key(
If you do not have the ability to override equality operators/Equals/GetHashCode as others have mentioned (as in, you do not control the source code of the object), you can provide an IEqualityComparer<Key>
implementation in the constructor of the dictionary to perform your equality checks.
class KeyComparer : IEqualityComparer<Key>
{
public bool Equals(Key x, Key y)
{
return x.Name == y.Name;
}
public int GetHashCode(Key obj)
{
return obj.Name.GetHashCode();
}
}
As it stands, your Key is a reference object, so equality is only determined on reference unless you tell the world (or the dictionary) otherwise.
1. Override Equals, Get Hash Code, and the '==' Operator.
The Key class must override Equals
in order for the Dictionary to detect if they are the same. The default implementation is going to check references only.
Here:
public bool Equals(Key other)
{
return this == other;
}
public override bool Equals(object obj)
{
if (obj == null || !(obj is Key))
{
return false;
}
return this.Equals((Key)obj);
}
public static bool operator ==(Key k1, Key k2)
{
if (object.ReferenceEquals(k1, k2))
{
return true;
}
if ((object)k1 == null || (object)k2 == null)
{
return false;
}
return k1.name == k2.name;
}
public static bool operator !=(Key k1, Key k2)
{
if (object.ReferenceEquals(k1, k2))
{
return false;
}
if ((object)k1 == null || (object)k2 == null)
{
return true;
}
return k1.name != k2.name;
}
public override int GetHashCode()
{
return this.name == null ? 0 : this.name.GetHashCode();
}
2. If Possible, use a struct.
You should use a struct for immutable datatypes like this, since they are passed by value. This would mean that you coulnd't accidentally munge two different values into the same key.
In order to use your own classes as dictionary keys, you should override GetHashCode and Equals. Otherwise it will use the memory address to check for equality.
public class Key { string name; public Key(string n) { name = n; } public override int GetHashCode() { return name.GetHashCode(); } public override bool Equals(object obj) { var other = obj as Key; if( other == null ) return false; return name == other.name; } }
You want true - but a and b are different objects.
You need to override GetHashCode and Equals on class Key
public class Key
{
string name;
public Key(string n) { name = n; }
public override int GetHashCode()
{
if (name == null) return 0;
return name.GetHashCode();
}
public override bool Equals(object obj)
{
Key other = obj as key;
return other != null && other.name == this.name;
}
}
Overriding a class' GetHashCode and Equals methods so that it will work properly in a dictionary is not a very good approach. The way a dictionary behaves should be an implementation detail of the dictionary, not of whatever class is being used as a key. You'll get into trouble when you want to use the class in different dictionaries with different behavior. Or if you don't have access to the class source code.
A better mouse trap is to give the dictionary its own comparer. For example:
using System;
using System.Collections.Generic;
class Program {
static void Main(string[] args) {
var d = new Dictionary<Key, int>(new MyComparer());
d.Add(new Key("A"), 1);
Console.WriteLine(d.ContainsKey(new Key("a")));
Console.ReadLine();
}
private class MyComparer : IEqualityComparer<Key> {
public bool Equals(Key x, Key y) {
return string.Compare(x.Name, y.Name, true) == 0;
}
public int GetHashCode(Key obj) {
return obj.Name.ToUpper().GetHashCode();
}
}
public class Key {
public string Name { get; set; }
public Key(string name) { Name = name; }
}
}
you need to override Equals and GetHashCode methods of your Key class.