Действительно ли это надежно для сравнения двух экземпляров класса путем сравнения их сериализированных массивов байтов?

Приведенный два примера класса, это хорошая и надежная практика для сравнения их serializaing их сначала и затем сравнение массивов байтов (или возможно хеши массивов). Эти объекты могли бы иметь сложные иерархические свойства, но сериализация должна пойти настолько же глубоко как требуется.

Для сравнения я имею в виду процесс проверки, что все propertis типов примитивов имеют равные значения, свойства составных типов имеют равные свойства типов примитивов и т.д. Что касается свойств набора, они должны быть равны друг другу: равные элементы, те же положения:

{'a','b','c'} != {'a','c','b'}



 {new Customer{Id=2, Name="abc"}, new Customer {Id=3, Name="def"}} 
    !=
 {new Customer{Id=3, Name="def"}, new Customer {Id=2, Name="abc"}}

но

 {new Customer{Id=2, Name="abc"}, new Customer {Id=3, Name="def"}}
    ==
 {new Customer{Id=2, Name="abc"}, new Customer {Id=3, Name="def"}}

И сериализацией я имею в виду стандартный бинарный форматтер.NET.

Спасибо.

12
задан Valentin Vasilyev 11 February 2010 в 15:29
поделиться

3 ответа

Вы запрашиваете гарантию, что сериализованное представление будет совпадать. Это будет ужасно сложно найти, BinaryFormatter - сложный класс. Потенциальной проблемой могут быть особенно сериализованные структуры, имеющие выравнивающую прокладку.

Гораздо проще привести пример, в котором он не будет соответствовать. System.Decimal имеет разные байтовые шаблоны для таких значений, как 0,01M и 0,010M. Его оператор == () скажет, что они равны, а его сериализованный байт [] - нет.

5
ответ дан 2 December 2019 в 22:37
поделиться

Вам придется еще точнее определить, что значит "равный".

Если одно из свойств является коллекцией, то могут быть различия в порядке (в результате определенных последовательностей добавления/удаления), которые могут быть или не быть существенными для вас. Подумайте о словаре, в котором одни и те же элементы были добавлены в разном порядке. Столкновение может привести к другому двоичному потоку.

2
ответ дан 2 December 2019 в 22:37
поделиться

Это надежно, если:

  1. Каждый отдельный класс в графе отмечен [Serializable] . Это не так просто, как может показаться; если вы сравниваете совершенно произвольные объекты, то есть довольно хороший шанс, что там есть что-то несериализуемое, над чем вам не хватает контроля.

  2. Вы хотите знать, в точности два экземпляра одинаковы.Имейте в виду, что BinaryFormatter в основном погружается во внутреннее состояние этих объектов, поэтому, даже если они кажутся одинаковыми в силу общедоступных свойств, они могут быть не такими. Если вы точно знаете, что граф создается одинаково в каждом экземпляре, возможно, вас это не волнует; но в противном случае между графиками может быть ряд скрытых различий.

    Этот момент также является более серьезной проблемой, чем можно было предположить на первый взгляд. Что, если вы решите поменять класс на интерфейс? У вас может быть два интерфейса, которые, насколько вы знаете, абсолютно одинаковы; они выполняют одну и ту же задачу и предоставляют одинаковые данные. Но это могут быть совершенно разные реализации. Что хорошо в IEquatable , так это то, что он не зависит от конкретного типа.

Таким образом, это сработает для значительного количества случаев, но я, вероятно, не считаю это хорошей практикой, по крайней мере, не зная всех подробностей о конкретном контексте, в котором он используется По крайней мере, я бы не стал полагаться на это как на общий метод сравнения для любых двух экземпляров; его следует использовать только в особых случаях, когда вы знаете о деталях реализации задействованных классов.

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

2
ответ дан 2 December 2019 в 22:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: