Подтвердить что ты не робот

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

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

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

{'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.

Спасибо.

4b9b3361

Ответ 1

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

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

Ответ 2

Вам нужно было бы определить, что здесь означает равное.

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

Ответ 3

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

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

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

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

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

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