Реализация класса географических координат: сравнение равенства

Я интегрирую класс географических координат из CodePlex в мою личную библиотеку «набор инструментов». Этот класс использует поля float для хранения широты и долготы.

Поскольку класс GeoCoordinate реализует IEquatable , я обычно писал метод примерно так:

public bool Equals(GeoCoordinate other)
{
    if (other == null) {
        return false;
    }

    return this.latitude == other.latitude && this.longitude == other.longitude;
}

На этом я остановился и подумал, что я сравниваю переменные с плавающей запятой на равенство, что обычно недопустимо. Затем мой мыслительный процесс шел примерно следующим образом:

  1. Я могу только представить себе установку свойств Широта и Долгота один раз, что означает, что не будет ошибок, которые будут накапливаться, чтобы испортить мои сравнения.

  2. С другой стороны, можно (хотя и бессмысленно) написать

     var geo1 = new GeoCoordinate (1.2, 1.2);
    var geo2 = new GeoCoordinate (1.2, 1.2);
    
     // geo1.Equals (geo2) определенно будет истинным, НО:
    
    geo2.Latitude * = 10;
    geo2.Latitude / = 10;
    
     // Я бы подумал, что теперь все ставки отключены
     

    Конечно, это не то, что я могу себе представить, но если открытый интерфейс класса позволяет это, тогда Equals сможет справиться с этим.

  3. Сравнение на равенство с использованием Разница тест решит проблему сравнения двух экземпляров, но создаст больше проблем:

    • Как сделать равенство транзитивным? Это звучит невероятно.
    • Как создать такой же хэш-код для всех значений, которые будут сравнивать равные?

      Предположим, что epsilon = 0,11 ( случайный пример). Отсюда следует, что для GeoCoordinate {1, 1} потребуется тот же хэш-код, что и для GeoCoordinate {1.1, 1.1} . Но для последнего потребуется тот же хэш-код, что и для GeoCoordinate {1.2, 1.2} . Вы можете видеть, к чему это идет: все экземпляры должны иметь одинаковый хэш-код .

  4. Решением всего этого было бы сделать GeoCoordinate неизменяемым классом. Это также решит проблему GetHashCode : он основан на широте и долготе (что еще), и если они изменяемы, то использование GeoCoordinate в качестве ключа в словаре запрашивает беда. Однако создание неизменяемого класса имеет свои недостатки:

    • Вы не можете создавать экземпляры класса и настраивать их (парадигма WPF), что в некоторых случаях может быть проблемой
    • Сериализация, вероятно, также станет проблемой из-за потери конструктора без параметров (я не эксперт по сериализации .NET, так что это столько подробностей, сколько я вижу здесь)

Какой подход вы бы предложили? Легко привести класс в соответствие с требованиями, которые у меня есть прямо сейчас (просто сделайте его неизменным), но есть ли какой-нибудь лучший способ?

Изменить : я добавил пункт 3 в список выше, сдвинув предыдущий пункт 3 в положение 4.

Решение

Я собираюсь дать еще немного времени для обратной связи,но сейчас я придерживаюсь неизменного подхода. Структуру (потому что это то, что она есть сейчас) с соответствующими элементами можно увидеть здесь ; комментарии и предложения более чем приветствуются.

11
задан Jon 21 July 2011 в 11:59
поделиться