代码之家  ›  专栏  ›  技术社区  ›  Valentin V

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

  •  12
  • Valentin V  · 技术社区  · 16 年前

    对于一个类的两个实例,通过先对它们进行序列化,然后比较字节数组(或者可能是数组的散列)来比较它们是一个好的、可靠的实践吗? 这些对象可能具有复杂的层次结构属性,但序列化应该尽可能深入。

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

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

    谢谢。

    3 回复  |  直到 15 年前
        1
  •  5
  •   Hans Passant    15 年前

    您要求保证序列化表示将匹配。这将是非常困难的,二进制格式化程序是一个复杂的类。特别是带有对齐填充的序列化结构可能是一个潜在的问题。

    更简单的是提供一个不匹配的例子。对于0.01m和0.010m这样的值,decimal有不同的字节模式。它的运算符==()表示它们相等,它的序列化字节[]则不相等。

        2
  •  2
  •   Henk Holterman    16 年前

    你必须更精确地定义什么是平等。

    如果其中一个属性是集合,则在顺序上(由于特定的添加/删除序列)可能存在差异,这对您来说可能重要,也可能不重要。想想一本字典,同样的元素是按不同的顺序添加的。碰撞可能导致不同的二进制流。

        3
  •  2
  •   Aaronaught    16 年前

    如果:

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

    2. 您想知道这两个实例是否 确切地 相同的。记住 BinaryFormatter 基本上是潜入这些物体的内部状态,所以即使它们因公共财产而看起来是一样的,它们也可能不是。如果您知道在每个实例中图形是以完全相同的方式创建的,那么您可能不关心这个问题;但是如果不关心,则图形之间可能存在许多隐藏的差异。

      这一点也是一个比人们可能首先怀疑的更严重的皱纹。如果您决定用一个接口交换类呢?据您所知,您可能有两个完全相同的接口;它们完成相同的任务并提供相同的数据。但它们可能是完全不同的实现。有什么好的 IEquatable 它独立于混凝土类型。

    所以这将 工作 对于大量的案例,但我可能不会认为这是一个好的实践,至少在不知道它所使用的特定上下文的所有细节的情况下。至少,我不会将此作为 任何 两个实例;它只能在您知道所涉及类的实现细节的特定情况下使用。

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

    推荐文章