为什么COM互操作将VB6布尔视为C#短整型?

4

我有一个遗留的VB6应用程序,它定义了以下结构:

Public Type DrawDown
    Date As Date
    Amount As Currency
    CapitaliseInterest As Boolean
End Type

使用 tlbimp.exe 生成的互操作程序集,但结构如下:

[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct DrawDown
{
    public DateTime Date;
    [MarshalAs(UnmanagedType.Currency)]
    public decimal Amount;
    public short CapitaliseInterest;
}

我正在使用.NET 4.0。

为什么VB6中的Boolean被翻译成C#中的short而不是bool


你确定你没有重新排列成员吗? - JaredPar
我确定。C# 代码是从 JustDecompile 打开的程序集中复制出来的。 - John Mills
我对VB6不够熟悉,无法确定字段是否被重新排序。但是,Davide关于实际类型的答案是正确的。 - JaredPar
嗯,我记不得VB6的打包规则了,所以我不知道这是否正确(如果我知道,它会与其他所有情况混淆在一起,要么某些东西必须对齐字边界,要么其他情况下某些东西则不能对齐字边界 :) 你有尝试编码来验证它是否有效吗?我必须承认我的好奇心被激发了。 - Jon Hanna
不,我会说它出了问题。我更新的问题中的代码片段包含来自 ILSpy 的输出,其中成员按与 VB6 代码相同的顺序排序。 JustDecompile 按错误的顺序排序了成员。 - John Mills
显示剩余4条评论
4个回答

12

VB6使用VARIANT_BOOL类型,

在这里找到关于它的信息和历史: BOOL vs. VARIANT_BOOL vs. BOOLEAN vs. boo

VARIANT_BOOL是由Visual Basic开发人员开发的。

typedef short VARIANT_BOOL; define VARIANT_TRUE ((VARIANT_BOOL)-1) define VARIANT_FALSE ((VARIANT_BOOL)0)。Basic使用-1表示“true”,0表示“false”,而VARIANT_BOOL旨在保留此行为。


8

这是因为它就是一个布尔值。

在VB6中,布尔值是16位的,其中0表示假,任何非零值表示真,但设置为真时为-1(0xFFFF)。这样,许多布尔值与数字的组合在VB6中都能很好地工作,因为x AND TRUE给出xx OR FALSE给出xx AND FALSE给出FALSE等等,在按位和布尔运算符方面也是同样的逻辑。不幸的是,这也意味着4 AND 2是假的,尽管它是TrueThing AND OtherTrueThing,因此谨慎的VB6程序员并没有过分依赖它,而是使用CBool强制该值为0或-1。

一般来说,我们可以选择使用自然机器大小以获得机器处理速度,或者使用单个字节,因为它是最小可寻址单元,因此具有尺寸优势。回顾16位机器上的自然大小,当然是16位,平衡更倾向于选择自然大小,而今天我们有32位和64位机器。Visual Basic 1.0在DOS和Windows 3.0上运行,这些系统可以在Intel 80286 16位处理器上运行,因此选择并不奇怪。

在COM世界中,我们有VARIANT_BOOL,这只是另一种说“像VB6一样处理布尔值”的方法,以实现跨语言兼容性。在C#中最接近的可能是shortushort,如果我们只关心C#,我们可以选择其中任何一个。首先,我们倾向于使用带符号的值而不是无符号的值,这会使我们倾向于short,但是ushort不是CLS兼容类型,引入与其他.NET语言不兼容没有任何意义!因此short是明显的选择。


2

Boolean在底层实质上是一个短整型:

False = 0, True != 0

生成Interop程序集可以解决这个问题。
参考MSDN的文档说明。
块引用: 4字节整数值,其中任何非零值表示true,0表示false。这是结构中布尔字段和平台调用中布尔参数的默认格式。

2
您可以在执行 tlbimp.exe 命令时传递 /VariantBoolFieldToBool 标志,这将使得其生成一个 C# bool 成员而不是 short 类型。

请参阅 tlbimp.exe 的官方文档

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接