Question

Jetez un oeil à cette classe:

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();
    }
}

J'ai aussi une classe Vector, qui est seulement deux points et d'autres atributs. Je ne veux pas avoir des points égaux dans mon vecteur, donc je suis venu avec cette méthode:

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;
        }

Et ce test unitaire, ce qui devrait me donner une exception:

    [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);
    }

Quand j'utilise le même point, qui est, mPoint1, comme dans le code l'exception est levée. Quand j'utilise mPoint2, même leur nom et les coordonnées étant les mêmes, l'exception n'est pas levée. J'ai vérifié leurs codes de hachage, et ils sont en différents de fait. Basé sur le code que je créé dans GetHashCode, je tought ces deux points aurait le même hashcode.

Quelqu'un peut-il me expliquer pourquoi cela ne fonctionne pas comme je tought ce serait? Je ne suis pas sûr que j'ai bien expliqué, mais .. Je vous remercie de l'aide: D

George

Était-ce utile?

La solution

Vous êtes la mise en œuvre IEqualityComparer<T> dans le type, il essaie de comparer - ce qui est très étrange. Vous devez certainement être tout mettre en œuvre IEquatable<T> et redéfinissent, plutôt Equals(object). Ce serait certainement faire votre travail de test unitaire.

La différence entre IEquatable<T> et IEqualityComparer<T> est que le premier est mis en œuvre par une classe à dire: « Je peux comparer me avec une autre instance du même type. » (Il ne Vous être le même type, mais il est habituellement.) Ceci est approprié s'il y a une comparaison naturelle - par exemple, la comparaison choisie par string est l'égalité ordinale - il faut que ce soit exactement la même séquence de valeurs de char.

IEqualityComparer<T> est différent - il peut comparer deux instances d'un type. Il peut y avoir plusieurs implémentations différentes de ce pour un type donné, donc il n'a pas d'importance si oui ou non une comparaison particulière est « le naturel » - il est juste obtenu d'être la bonne pour votre travail. Ainsi, par exemple, vous pourriez avoir une classe de Shape et d'égalité différents comparateurs pour comparer les formes par la couleur, la zone ou quelque chose comme ça.

Autres conseils

Vous devez passer outre Object.Equals aussi bien.

Ajouter à votre mise en œuvre:

// 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;
}

Je puis retravaille votre autre mise en œuvre d'utiliser le premier, ainsi que d'ajouter les contrôles null approprié.

public bool Equals(MemorialPoint x, MemorialPoint y)
{
    if (x == null)
        return (y == null);
    return x.Equals(y);
}

Vous devez également repenser votre concept d ' « égalité », car il n'est pas actuellement réuni .NET cadre des exigences href="http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx" rel="nofollow noreferrer"> .

Si possible, je recommande une nouvelle conception avec un dépôt d'objets point commémoratifs (éventuellement par nom calée), de sorte que l'égalité de référence simple peut être utilisé.

Vous avez mis une étiquette ArcObjects à ce sujet, donc je pensais juste que je mentionne IRelationalOperator.Equals . Je ne l'ai jamais testé pour voir si cette méthode rend hommage à la tolérance au groupe de références spatiales de la géométrie. Cela peut être réglé en utilisant ISpatialReferenceTolerance.XYTolerance .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top