Pregunta

Tome un vistazo a esta clase:

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

I también tienen una clase de vector, que es simplemente dos puntos y algunos otros atributos. Yo no quiero tener igualdad de puntos en mi vector, por lo que me ocurrió con este método:

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

Y esta unidad de prueba, lo que me debe dar una excepción:

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

Cuando uso el mismo punto, es decir, mPoint1, como en el código de la excepción. Cuando uso mPoint2, incluso su nombre y las coordenadas sean las mismas, la excepción no se lanza. Revisé sus códigos hash, y son de hecho diferentes. Basado en el código que he creado en GetHashCode, me listada estos dos puntos tendría el mismo código hash.

Puede alguien me explique por qué esto no está funcionando como lo enseñado que lo haría? No estoy seguro de lo expliqué bien, pero .. Agradezco la ayuda: D

George

¿Fue útil?

Solución

Esta implementación IEqualityComparer<T> dentro del tipo que está tratando de comparar - lo cual es muy raro. Usted debe casi seguro que sólo puede ser la aplicación de IEquatable<T> y anulando Equals(object) lugar. Eso sería sin duda hacer su trabajo de prueba de unidad.

La diferencia entre IEquatable<T> y IEqualityComparer<T> es que el primero es implementada por una clase a decir: "Puedo comparar yo con otra instancia del mismo tipo." (No hace Tienes a ser del mismo tipo, pero por lo general es.) Esto es apropiado si hay una comparación naturales - por ejemplo, la comparación elegido por string es la igualdad ordinal - que tiene que ser exactamente la misma secuencia de valores char.

Ahora IEqualityComparer<T> es diferente - se puede comparar dos instancias de un tipo. Puede haber varias implementaciones diferentes de este para un tipo determinado, por lo que no importa si es o no una comparación particular es "al natural" - es sólo llegó a ser el más adecuado para su trabajo. Así, por ejemplo, usted podría tener una clase Shape, y los diferentes comparadores de igualdad para comparar formas por color, área o algo por el estilo.

Otros consejos

Necesita anular Object.Equals también.

Añadir esto a su aplicación:

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

Me gustaría entonces Rehago su otra aplicación para usar la primera, además de añadir los cheques nulos apropiado.

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

También es necesario reflexionar sobre el concepto de "igualdad", ya que no ha logrado actualmente .NET marco de exigencias .

Si es posible, recomiendo un re-diseño con un repositorio de objetos de punto conmemorativos (posiblemente introducido por su nombre), por lo que la igualdad simple referencia se puede utilizar.

Usted ha puesto una etiqueta de ArcObjects en esto, así que pensé que me gustaría mencionar IRelationalOperator.Equals . Nunca he probado para ver si este método rinde homenaje a la tolerancia cluster de referencias espaciales de las geometrías. Esto se puede ajustar usando ISpatialReferenceTolerance.XYTolerance .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top