【发布时间】:2011-01-29 14:12:02
【问题描述】:
OLE 变体,被旧版本的 Visual Basic 使用并且在 COM 自动化中普遍使用,可以存储许多不同的类型:基本类型,如整数和浮点数,更复杂的类型,如字符串和数组,一直到 @987654321 @ 实现和ByRef 变体形式的指针。
变体也是弱类型的:它们将值转换为另一种类型而不会发出警告,具体取决于您应用的运算符以及传递给运算符的值的当前类型。例如,比较两个变量,一个包含整数 1,另一个包含字符串 "1",如果相等,将返回 True。
因此,假设我在底层数据级别使用变体(例如 C++ 中的 VARIANT 或 Delphi 中的 TVarData - 即不同可能值的大联合),我应该如何一致地散列变体以便它们遵守正确的规则?
规则:
- 散列不相等的变体在排序和直接相等时都应该比较为不相等
- 对于排序和直接相等比较为相等的变体应哈希为相等
如果我必须使用不同的排序和直接比较规则以使散列适合,那也没关系。
我目前的工作方式是将变体规范化为字符串(如果它们适合),并将它们视为字符串,否则我正在处理变体数据,就好像它是一个不透明的 blob 一样,并散列并比较其原始字节。当然,这有一些限制:数字1..10 排序为[1, 10, 2, ... 9] 等。这有点烦人,但它是一致的,而且工作量很小。但是,我确实想知道这个问题是否有公认的做法。
【问题讨论】:
-
VARIANT 实际上是一个结构,它有两个数据——值和类型。您的比较和转换声明似乎只考虑了值,而不考虑该结构的类型字段。正确的方法是始终考虑提交的类型。
-
@Franci,我认为你没有抓住重点。即使它们的类型不同,两个变体也可以比较相等。如果变体比较相等,那么 Barry 也希望它们的哈希值相等。
Variant(1) = Variant('1')==>hash(Variant(1)) = hash(Variant('1')). -
巴里,我不认为你的第一条规则是正确的。它忽略了散列冲突的可能性,其中散列相等但值根本不相似。
-
你说得对@Rob,我的意思是相反的——我把它倒过来了。虽然我认为它实际上遵循第二条规则。
-
如果 Barry 想要语义相等,即任何 VARIANT 类型中数字 1 的任何表示都被视为相同(包括字符串、日期和对象(无论如何,1 的 IDispatch 或 OLEDATE 表示是什么?) ) 并且要具有相同的散列,他应该在计算散列时考虑类型,或者应该将所有表示“标准化”为相同的数据类型(他目前似乎正在这样做)。如果他选择“规范化”方法,则 VARIANT 部分与问题绝对无关,因为同样的问题适用于他选择的任何其他值存储。
标签: c++ delphi winapi com variant