判断对象是否被修改的最佳方法是什么?
我有一个对象,该对象作为序列化的base-64字符串映射到cookie。我只想写出一个新的cookie,如果对服务器端存储在cookie中的对象进行了更改。
我想做的是,当从Cookie /初始化对象中提取对象时获得哈希码,然后将原始哈希码与将Cookie标头发送给客户端之前存在的哈希码进行比较,以确保没有重新序列化/发送cookie,除非进行了更改。
我打算重写.NET的Object.GetHashCode()方法,但是我不确定这是否是检查对象是否被修改的最佳方法。
还有其他方法可以检查对象是否被修改,还是应该重写GetHashCode()方法。
更新我决定接受@rmbarnes的答案,因为它对问题有一个有趣的解决方案,并且因为我决定在他的帖子结尾使用他的建议,而不是检查修改。但是,我仍然有兴趣听到任何其他人可能对我的方案有任何解决方案。
解决方案
回答
GetHashCode()应该始终与Equals()保持同步,并且不一定要确保Equals()会检查对象中的所有字段(在某些情况下,我们不希望这样做)。
此外,不能保证GetHashCode()返回所有可能的对象状态的唯一值。可以想象(尽管不太可能),两个对象状态可能导致相同的HashCode(毕竟,它仅具有int的可能状态;有关更多详细信息,请参见Pigeonhole原理)。
如果可以确保Equals()检查所有适当的字段,则可以克隆该对象以记录其状态,然后针对新状态使用Equals()对其进行检查以查看其是否已更改。
顺便说一句:我们提到的序列化给了我一个主意。我们可以序列化对象,进行记录,然后在检查对象更改时,重复该过程并比较序列化的值。这样一来,我们无需检查对象的任何代码即可检查状态更改。但是,这不是一个很好的解决方案,因为:
- 这可能效率很低
- 对象中的序列化更改很容易;我们可能会在对象状态更改上得到误报。
回答
我个人会说要按照计划进行。.好的哈希码是查看对象是否"按原样"的最佳方式。.我们可以查看大量的哈希算法,请查看明显的Wikipedia页面。哈希函数,然后从那里去。
覆盖GetHashCode并继续使用它!只要确保信息的所有元素都构成哈希的一部分即可:)
回答
在对象的构造函数的末尾,我们可以将对象序列化为基本64字符串,就像cookie存储它一样,然后将其存储在成员变量中。
当我们要检查是否需要重新创建cookie时,请重新序列化该对象,并将此新的base 64字符串与成员变量中存储的字符串进行比较。如果已更改,请使用新值重置Cookie。
当心陷阱,不要在序列化本身中包含存储base 64序列化的成员变量。我假设语言使用了sleep()函数(即PHP的工作方式)之类的东西来对其自身进行序列化,因此只需确保该函数中不包含该成员即可。
这将始终有效,因为我们正在比较要保存在Cookie中的确切值,并且不需要覆盖GetHashCode(),这听起来可能会带来讨厌的后果。
所有这些,我可能只是放弃测试并始终重置cookie,与进行更改检查相比,其中的开销不会太大,而且错误发生的可能性也要小得多。
回答
令我感到奇怪的是,为什么要在服务器端和客户端都存储相同的对象,特别是如果我们在每次旅行中都将它们进行比较时。
我猜想反序列化cookie并将其与服务器端对象进行比较在性能上等同于再次序列化该对象。
但是,如果我们想这样做,我会将序列化的服务器端对象与cookie的值进行比较,并进行相应的更新。最坏的情况是,我们无意中进行了序列化。最好的情况是,我们进行了字符串比较。
另一种方法是反序列化和比较对象,最糟糕的情况是反序列化,比较n个字段然后进行序列化。最好的情况是反序列化和比较n个字段。