Reputation: 10015
I'm getting the first key in a dictionary and comparing it with a lookup value. They are the same, but when I try to access the key from the dictionary I get a KeyNotFoundException
:
public void Draw(Graphics graphics, Shape shape)
{
foreach (var line in shape.Lines)
{
var tuple = shape.LinesToNurmalDictionary.Keys.First();
bool equals = tuple == line;
bool referenceEquals = ReferenceEquals(tuple, line);
var invisible = shape.LinesToNurmalDictionary[line].All(x => x.Z < 0);
How can I fix it?
Added: Dictionary is
Dictionary<Tuple<ShapePoint, ShapePoint>, List<ShapePoint>> LinesToNurmalDictionary;
So i 'solved' my problem by using my own class instead of Tuple, but actualy question still unresponsed:
public class Line
{
public ShapePoint A { get; set; }
public ShapePoint B { get; set; }
public List<ShapePoint> Normals { get; set; }
public Line(ShapePoint a, ShapePoint b)
{
A = a;
B = b;
Normals = new List<ShapePoint>();
}
private sealed class DefaultEqualityComparer : IEqualityComparer<Line>
{
public bool Equals(Line x, Line 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 Equals(x.A, y.A) && Equals(x.B, y.B);
}
public int GetHashCode(Line obj)
{
unchecked
{
return ((obj.A != null ? obj.A.GetHashCode() : 0)*397) ^ (obj.B != null ? obj.B.GetHashCode() : 0);
}
}
}
private static readonly IEqualityComparer<Line> DefaultComparerInstance = new DefaultEqualityComparer();
public static IEqualityComparer<Line> DefaultComparer
{
get
{
return DefaultComparerInstance;
}
}
}
Upvotes: 1
Views: 992
Reputation: 61952
As tia already said in a comment, this happens because an entry is first added to the Dictionary<,>
where the hash code of the key (here the Tuple<ShapePoint, ShapePoint>
) has some value which is "saved" and kept by the Dictionary<,>
. After that the key object is "mutated" (modified) in a way that changes its hash code. This leads to the Dictionary<,>
being in a corrupt state.
Therefore when the key is searched for afterwards, it is not found. Its "new" hash code differs from the hash the Dictionary<,>
thinks this key has.
Do not modify objects that might be keys in a Dictionary<,>
(or members of a HashSet<>
and so on) in a way that changes their hash codes.
Here's an example illustrating. The type:
class Changeable
{
public int Prop { get; set; }
public override int GetHashCode()
{
return Prop;
}
public override bool Equals(object obj)
{
return Equals(obj as Changeable);
}
public bool Equals(Changeable other)
{
if (other == null)
return false;
return GetType() == other.GetType() && Prop == other.Prop;
}
}
The code that gives the same problem:
var onlyInstance = new Changeable();
var dict = new Dictionary<Changeable, string>();
onlyInstance.Prop = 1;
dict.Add(onlyInstance, "what-ever");
onlyInstance.Prop = 2;
string restoredValue = dict[onlyInstance]; // throws!
Upvotes: 2