iequalitycompererと奇妙な結果
-
29-09-2019 - |
質問
このクラスを見てください:
public class MemorialPoint:IMemorialPoint,IEqualityComparer<MemorialPoint>
{
private string _PointName;
private IPoint _PointLocation;
private MemorialPointType _PointType;
private DateTime _PointStartTime;
private DateTime _PointFinishTime;
private string _NeighborName;
private double _Rms;
private double _PointPdop;
private double _PointHdop;
private double _PointVdop;
// getters and setters omitted
public bool Equals(MemorialPoint x, MemorialPoint y)
{
if (x.PointName == y.PointName)
return true;
else if (x.PointName == y.PointName && x.PointLocation.X == y.PointLocation.X && x.PointLocation.Y == y.PointLocation.Y)
return true;
else
return false;
}
public int GetHashCode(MemorialPoint obj)
{
return (obj.PointLocation.X.ToString() + obj.PointLocation.Y.ToString() + obj.PointName).GetHashCode();
}
}
また、ベクトルクラスもあります。これは、2つのポイントと他の控えめなものです。私は自分のベクトルに平等なポイントを持ちたくないので、この方法を思いつきました:
public void RecalculateVector(IMemorialPoint fromPoint, IMemorialPoint toPoint, int partIndex)
{
if (fromPoint.Equals(toPoint))
throw new ArgumentException(Messages.VectorWithEqualPoints);
this.FromPoint = FromPoint;
this.ToPoint = ToPoint;
this.PartIndex = partIndex;
// the constructDifference method has a weird way of working:
// difference of Point1 and Point 2, so point2 > point1 is the direction
IVector3D vector = new Vector3DClass();
vector.ConstructDifference(toPoint.PointLocation, fromPoint.PointLocation);
this.Azimuth = MathUtilities.RadiansToDegrees(vector.Azimuth);
IPointCollection pointCollection = new PolylineClass();
pointCollection.AddPoint(fromPoint.PointLocation, ref _missing, ref _missing);
pointCollection.AddPoint(toPoint.PointLocation, ref _missing, ref _missing);
this._ResultingPolyline = pointCollection as IPolyline;
}
そして、このユニットテストは、私に例外を与えるはずです:
[TestMethod]
[ExpectedException(typeof(ArgumentException), Messages.VectorWithEqualPoints)]
public void TestMemoriaVector_EqualPoints()
{
IPoint p1 = PointPolygonBuilder.BuildPoint(0, 0);
IPoint p2 = PointPolygonBuilder.BuildPoint(0, 0);
IMemorialPoint mPoint1 = new MemorialPoint("teste1", p1);
IMemorialPoint mPoint2 = new MemorialPoint("teste1", p2);
Console.WriteLine(mPoint1.GetHashCode().ToString());
Console.WriteLine(mPoint2.GetHashCode().ToString());
vector = new MemorialVector(mPoint1, mPoint1, 0);
}
コードのように、同じポイント、つまりMpoint1を使用する場合、例外はスローされます。 mpoint2を使用する場合、名前と座標が同じでさえ、例外はスローされません。私は彼らのハッシュコードをチェックしましたが、実際には異なります。 GethashCodeで作成したコードに基づいて、これらの2つのポイントが同じハッシュコードを持つことを考えました。
誰かが私にこれが私がそれを見たように機能していない理由を説明できますか?私はこれをよく説明したかどうかわかりませんが、私は助けに感謝します:D
ジョージ
解決
あなたは実装しています IEqualityComparer<T>
タイプ内で比較しようとしています - これは非常に奇妙です。ほぼ確実に実装する必要があります IEquatable<T>
そしてオーバーライド Equals(object)
代わりは。それは間違いなくあなたのユニットテストを機能させるでしょう。
間の違い IEquatable<T>
と IEqualityComparer<T>
前者はクラスによって実装されているということです。 私自身 同じタイプの別のインスタンスで。」(そうではありません 持ってる 同じタイプであることですが、通常はそうです。)これは、自然な比較がある場合に適切です - たとえば、によって選択された比較は string
順序の平等です - それはまったく同じシーケンスでなければなりません char
値。
今 IEqualityComparer<T>
異なる - タイプの任意の2つのインスタンスを比較できます。特定のタイプのこれには複数の異なる実装がある可能性があるため、特定の比較が「自然なもの」であるかどうかは関係ありません。したがって、たとえば、 Shape
クラス、および異なる平等と比較して、色、面積、またはそのようなものによる形状を比較します。
他のヒント
オーバーライドする必要があります Object.Equals
同じように。
これを実装に追加します:
// In MemorialPoint:
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;
MemorialPoint y = obj as MemorialPoint;
if (this.PointName == y.PointName)
return true;
else if (this.PointName == y.PointName && this.PointLocation.X == y.PointLocation.X && this.PointLocation.Y == y.PointLocation.Y)
return true;
else
return false;
}
その後、他の実装を再加工して最初の実装を使用し、さらに適切なヌルチェックを追加します。
public bool Equals(MemorialPoint x, MemorialPoint y)
{
if (x == null)
return (y == null);
return x.Equals(y);
}
あなたはこれにarcobjectsタグを付けたので、私はちょうど私が言及したと思いました IrelationalOperator.equals. 。この方法が幾何学の空間参照のクラスター許容度を尊重するかどうかを確認するためにテストしたことはありません。これを使用して調整できます ispatialRecerenceTolerance.xytolance.