Этот вопрос подобен тому здесь.
Все мы знаем, каков PointF, не так ли? Это - структура данных:
public struct PointF
{
public float X;
public float Y;
}
Как реализовать IEqualityComparer
с допуском? Скажем, мой Equals
код похож на это
public const float Epsilon = 0.01; //say
public bool Equals(PointF pt1, PointF pt2)
{
return Math.Abs(pt1.X-pt2.X)
Вопрос: Как реализовать корректное GetHashCode
так, чтобы для словаря PointF
, Я получу доступ к элементу правильно?
Я взламываю голову несколько дней, но все еще не могу найти удовлетворительное решение.
Вместо того, чтобы определять толерантность на расстоянии, вы могли бы разместить точки в сетке.
Если две точки находятся в одной ячейке, они считаются равными и имеют тот же хэш-код.
public bool Equals(PointF pt1, PointF pt2)
{
return GetCell(pt1.X) == GetCell(pt2.X)
&& GetCell(pt1.Y) == GetCell(pt2.Y);
}
public int GetHashCode(PointF pt)
{
return GetCell(pt.X) ^ GetCell(pt.Y);
}
private static int GetCell(float f)
{
return (int)(f / 10); // cell size is 10 pixels
}
Тезис: Не существует реализации равных
и gethashCode
, который соответствует вашим требованиям.
Доказательство: Рассмотрим следующие три точки, A, B и C:
согласно вашим требованиям,
Equals(A, B) == true // (i)
Equals(B, C) == true // (ii)
Equals(A, C) == false // (iii)
GetHashCode(A) == GetHashCode(B) // (iv)
GetHashCode(B) == GetHashCode(C) // (v)
GetHashCode(A) != GetHashCode(C) // (vi)
, но из (IV) и (V) следует
GetHashCode(A) == GetHashCode(C)
и, таким образом,
Equals(A, C) == true
который противоречит (III) и (VI).
С равно
и GethashCode
не может вернуть разные значения для тех же аргументов, нет реализации, которая соответствует вашим требованиям.
Q.E.D.
Не думаю, что это возможно, потому что можно иметь бесконечную последовательность значений, равных (в пределах допуска) предыдущему и следующему значению в последовательности, но не любое другое значение, и GetHashCode
должен будет вернуть одинаковое значение для всех из них.