通过比较它们的序列化字节数组来比较类的两个实例是否可靠?

给定一个类的两个实例,通过首先对它们进行序列化然后比较字节数组(或者可能是数组的哈希值)来比较它们是一种好的和可靠的做法。 这些对象可能具有复杂的层次结构属性,但序列化应尽可能深入。

相比之下,我指的是确保原始类型的所有属性具有相等值的过程,复杂类型的属性具有基本类型的相同属性等。至于集合属性,它们应该彼此相等:相等的元素,相同的位置:

{'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二进制格式化程序。

谢谢。

您要求保证序列化表示将匹配。 这将是非常难以实现的,BinaryFormatter是一个复杂的类。 特别是具有对齐填充的序列化结构可能是潜在的问题。

更简单的是提供一个不匹配的例子。 System.Decimal对于0.01M和0.010M等值具有不同的字节模式。 它的运算符==()会说它们是相等的,它的序列化字节[]不会。

你必须更精确地定义这里的平等意义。

如果其中一个属性是集合,则可能存在顺序差异(由于特定的添加/删除序列),这些差异可能对您有意义,也可能不重要。 想想一个字典,其中相同的元素以不同的顺序添加。 冲突可能导致不同的二进制流。

它是可靠的,如果:

  1. 图中的每个类都标记为[Serializable] 。 这并不像听起来那么简单; 如果你比较完全任意的对象,那么很有可能存在一些你无法控制的非序列化的东西。

  2. 您想知道这两个实例是否完全相同 。 请记住, BinaryFormatter基本上是潜入这些对象的内部状态,所以即使它们看起来由于公共属性而相同,它们也可能不是。 如果你知道图形在每个实例中以完全相同的方式创建的事实,也许你不关心这个; 但如果没有,图表之间可能存在许多隐藏的差异。

    这一点也是一个比人们可能首先怀疑的更严重的皱纹。 如果您决定使用接口替换类,该怎么办? 您可能有两个接口,据您所知,它们完全相同; 他们完成相同的任务并提供相同的数据。 但它们可能是完全不同的实现。 IEquatable在于它独立于具体类型。

因此,对于大量案例,这将是有效的,但我可能不会认为这是一个好习惯,至少在不知道有关它所使用的特定上下文的所有细节的情况下。至少,我不会依赖于此作为任何两个实例的通用比较方法; 它应该仅在您了解所涉及的类的实现细节的特定情况下使用。

当然,有些人可能会说编写任何依赖于类的实现细节的代码总是不好的做法。 我对此的看法更为适应,但需要考虑的是 – 依赖类的实现细节可能会导致以后难以维护的代码。