Контрольная сумма объектов в памяти

2

Позволяет сказать, что у меня есть класс A, который наследуется от класса B в С#. Класс B имеет свойство на нем под названием Checksum, которое при вызове во время выполнения вычисляет контрольную сумму всех свойств экземпляра класса A (используемый алгоритм контрольной суммы particualr не важен, возможно, один из BCL).

Важно отметить, что алгоритм контрольной суммы должен игнорировать свойство контрольной суммы, иначе он будет терпеть неудачу после подтверждения позже (поскольку значение контрольной суммы будет изменено).

Итак, насколько я вижу, есть два варианта:

1) Итерация по всем общедоступным свойствам объекта с использованием отражения, конкатенация в строку и контрольную сумму, которая.

2) Представьте, что объект является просто связкой смежных адресов memeory и рассматривает это как массив байтов и контрольную сумму, которая.

1 - звучит медленно 2 - звучит сложно, так как я не уверен, как вы его проигнорируете строку, которая представляет собой контрольную сумму, или как обрабатываются ссылки на другие объекты.

Есть ли у кого-нибудь лучшие идеи, чем 1, который звучит лучше, чем эти два решения?

Теги:
checksum

3 ответа

5
Лучший ответ

Вы можете украсить свойство контрольной суммы как NonSerialized и сериализовать экземпляр класса в массив байтов, а затем вычислить контрольную сумму. Таким образом, свойство будет игнорироваться при сериализации.

  • 0
    Это звучит как немного более элегантная реализация (1) выше, но, по сути, то же самое, я понимаю, что сериализация будет использовать отражение где-то внутри и является относительно медленной. Если не будет предложено никаких других «новых» решений, я бы посчитал, что это способ сделать это.
  • 1
    @Colin Вы можете сделать это быстрее: codebetter.com/blogs/gregyoung/archive/2008/08/24/…
Показать ещё 1 комментарий
2

Почему это должно быть свойство? Если бы это был метод, GetChecksum(), то вам не нужно было бы иметь какую-либо специальную логику, чтобы он не включал себя в расчет контрольной суммы. Теперь то, что вы создали, почти точно такое же, как и для существующего метода GetHashCode(), - просто предоставите реализацию этого.

Как правило, для каждого класса явным образом кодировал бы GetHashCode(), хотя быстрый веб-поиск будет показывать подходы, которые используют отражение, чтобы обеспечить общий (хотя и медленный) механизм. Обычно у каждого поля требуется включить в хэш-код, преобразовать его в целое число и умножить на фиксированное число, так что разные объекты с разными значениями полей дают разные хэш-коды, которые хорошо распределены по целочисленному диапазону.

В качестве примера Resharper генерирует методы GetHashCode(), которые выглядят следующим образом:

public override int GetHashCode()
{
    unchecked
    {
        int result = a;
        result = (result * 397) ^ (b != null ? b.GetHashCode() : 0);
        result = (result * 397) ^ c.GetHashCode();
        return result;
    }
}

Где a - int, b - строка, а c - длинная. Промежуточное значение (результат) умножается на 397 и помещается в мощность следующего хэш-кода компонента на каждом шаге. Непроверенный означает, что если целое число переполнено (что вполне вероятно), мы отбрасываем переполнение и обертываем. В большинстве случаев это должно обеспечить разумное покрытие целочисленного пространства - хотя я бы рекомендовал тестировать покрытие, поскольку плохой хэш-код может иметь серьезные последствия для производительности вашей системы.

Следует соблюдать осторожность при обработке нулей любого поля, чтобы вы не умножались на ноль и заканчивали большим количеством объектов, все из которых имеют нулевой хеш-код.

  • 0
    Интересный подход. Причина этого свойства заключается в том, что значение контрольной суммы необходимо сохранить в базе данных с использованием Linq2SQL или EF4, поэтому его использование в качестве свойства делает это отображение очень простым. Для наших целей (некоторый уровень безопасности) нам понадобится «хорошо известный» алгоритм, такой как MD5, для вычисления контрольной суммы.
  • 0
    Хорошо, в этом случае вы не должны использовать хеш-код, поскольку он не обязательно будет одинаковым для всех процессов или последующих запусков процесса. Подход сериализации, вероятно, лучше подойдет вам.
1

Вариант 3 заключается в создании метода "на лету", который вычисляет контрольную сумму всех свойств, например. используя отражение .emit. Это неэффективно для первого вызова, но сгенерированный метод может быть кэширован. Если вы знаете, какие типы должны быть запрограммированы, вы также можете использовать генерацию кода для создания контрольных методов для них во время компиляции.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню