【问题标题】:Checksumming objects in memory对内存中的对象进行校验和
【发布时间】:2010-01-18 11:36:27
【问题描述】:

假设我有一个从 C# 中的 B 类继承的 A 类。 B 类有一个名为 Checksum 的属性,当在运行时调用时,它会计算 A 类实例上所有属性的校验和(使用的特定校验和算法并不重要,可能来自 BCL)。

重要的是,校验和算法必须忽略校验和属性,否则稍后验证时它会失败(因为校验和值会改变)。

所以,据我所知,有两种选择:

1) 使用反射遍历对象的所有公共属性,连接成一个字符串并对其进行校验和。

2) 假设对象只是一堆连续的内存地址,并将其视为字节数组并对其进行校验和。

1 - 听起来很慢 2 - 听起来很困难,因为我不确定你如何让它忽略代表校验和本身的字符串,或者如何处理对其他对象的引用。

有没有人有任何比 1 更好的想法,这听起来像是这两种解决方案中的更好?

【问题讨论】:

    标签: c# checksum


    【解决方案1】:

    您可以将校验和属性装饰为NonSerialized,并将类的实例序列化为字节数组,然后计算校验和。这样在序列化时该属性将被忽略。

    【讨论】:

    • 这听起来像是上面 (1) 的一个稍微优雅的实现,但本质上是一样的,我知道序列化将在内部某处使用反射并且相对较慢。如果没有提出其他“新颖”的解决方案,那么我会认为这是这样做的方法。
    • 如果我正确理解您的链接,这个“快速序列化程序”要求您为每种类型实现手动序列化方法。如果 OP 只想要一个校验和,那么为每种类型编写一个自定义校验和方法不是更简单吗? (不过链接不错!)
    【解决方案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 是 string,c 是 long。中间值(结果)乘以 397,并在每个步骤中使用下一个组件的哈希码。未检查意味着如果整数溢出(这很可能),那么我们丢弃溢出并环绕。在大多数情况下,这应该可以合理地覆盖整数空间——尽管我建议测试覆盖率,因为糟糕的哈希码会对系统性能产生严重后果。

    应注意处理任何字段的零,以免乘以零并最终得到大量哈希码为零的对象。

    【讨论】:

    • 有趣的方法。该属性的原因是 Checksum 值将使用 Linq2SQL 或 EF4 持久化到数据库中,因此将其作为属性使映射非常简单。出于我们的目的(某种程度的安全),我们需要使用“众所周知”的算法,例如 MD5 来计算校验和。
    • 好的,在这种情况下,您不应该使用哈希码,因为不能保证跨进程或进程的后续运行都相同。序列化方法可能更适合您。
    【解决方案3】:

    选项 3 是动态创建一个方法来计算所有属性的校验和,例如通过使用反射.emit。这只对第一次调用效率低下,但生成的方法可以被缓存。如果您知道必须对哪些类型进行校验和,您还可以使用代码生成在编译时为它们创建校验和方法。

    【讨论】:

      猜你喜欢
      • 2012-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-08
      • 2011-07-18
      相关资源
      最近更新 更多