Я новичок в C #. Возможно, я не реализую IEquatable
должным образом, потому что объекты моего типа, которые следует считать одинаковыми, не являются.
Класс:
class CompPoint : IComparable {
public int X;
public int Y;
public CompPoint(int X, int Y) {
this.X = X;
this.Y = Y;
}
public override bool Equals(Object o) {
if (!(o is CompPoint)) {
throw new ArgumentException(String.Format("argument is not a CompPoint (%s given)", o));
}
CompPoint cp = (CompPoint)o;
return this.X == cp.X && this.Y == cp.Y;
}
public override int GetHashCode() {
int hash = base.GetHashCode(); // this is a problem. replace with a constant?
hash = (hash * 73) + this.X.GetHashCode();
hash = (hash * 73) + this.Y.GetHashCode();
return hash;
}
}
(Это нечто большее, чем CompPoint
, которое оправдывает его как класс.)
Затем этот тест не пройден:
[TestMethod()]
public void compPointTest() {
Assert.AreEqual(new CompPoint(0, 0), new CompPoint(0, 0));
}
Что я неправильно понимаю? Assert.AreEqual()
использует ссылочное равенство? Моя Equals()
функция в CompPoint
испорчена?
Эта функция также не срабатывает:
public void EqualsTest() {
Assert.IsTrue(new CompPoint(1, 1).Equals(new CompPoint(1, 1)));
}
Причина этого в том, что я использую Dictionary
, и он работает не так, как я надеюсь, что он будет:
[TestMethod()]
public void dictCompPointTest() {
IDictionary<CompPoint, int> dict = new Dictionary<CompPoint, int>();
dict[new CompPoint(0, 0)] = 4;
dict[new CompPoint(0, 0)] = 24;
dict[new CompPoint(0, 0)] = 31;
Assert.AreEqual(31, dict[new CompPoint(0, 0)]);
Assert.AreEqual(1, dict.Count);
}
Тест не пройден с этим сообщением:
Метод испытания
ShipAILabTest.BoardUtilsTest.dictCompPointTest
бросил исключение:
System.Collections.Generic.KeyNotFoundException:
Данный ключ отсутствовал в
словарь.
Этот тест отражает мои ожидания. Я надеюсь, что, поскольку ключ каждый раз идентичен, значение будет перезаписано. Что Dictionary
использует для проверки на равенство?
ОБНОВЛЕНИЕ: Я добавил функцию равенства, согласно предложению Томаса, и теперь CompPoint
тесты сравнения работают, и dictCompPointTest
работает.
public override bool Equals(Object o) {
if (!(o is CompPoint)) {
throw new ArgumentException(String.Format("argument is not a CompPoint (%s given)", o));
}
CompPoint cp = (CompPoint)o;
return this.X == cp.X && this.Y == cp.Y;
}
Таинственно, этот тест по-прежнему не проходит:
[TestMethod()]
public void dictCPTest2() {
IDictionary<CompPoint, int> dict = new Dictionary<CompPoint, int>();
dict[new CompPoint(2, 2)] = 2;
dict[new CompPoint(2, 2)] = 2;
Assert.AreEqual(1, dict.Count);
}
Проверка также не проходит, если ключи new CompPoint(4, 1)
, но не когда ключи new CompPoint(0, 1)
. Почему это может работать для некоторых значений, а не для других?
Больше загадок: функция хеш-кода, кажется, работает довольно плохо. Этот тест не пройден:
[TestMethod()]
public void hashCodeTest() {
int x = 0;
int y = 0;
Assert.AreEqual(new CompPoint(x, y).GetHashCode(), new CompPoint(x, y).GetHashCode());
}
Функция хеш-кода указана выше. В чем здесь проблема? Разве два CompPoint
объекта не должны иметь одинаковый хеш-код? Может быть, мой звонок на base.getHashCode()
является проблемой?