Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does COM Interop treat a VB6 Boolean as C# Short?

I have a legacy VB6 application that has the following structure defined:

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

An interop assembly is generated using tlbimp.exe but the structure ends up as the following:

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

I'm using .NET 4.0.

Why does the VB6 Boolean get translated to a C# short instead of a bool?

like image 848
John Mills Avatar asked Nov 29 '22 09:11

John Mills


2 Answers

VB6 uses the VARIANT_BOOL type,

find info and history about it here: BOOL vs. VARIANT_BOOL vs. BOOLEAN vs. boo

Off to the side came VARIANT_BOOL.

typedef short VARIANT_BOOL; define VARIANT_TRUE ((VARIANT_BOOL)-1) define VARIANT_FALSE ((VARIANT_BOOL)0) This was developed by the Visual Basic folks. Basic uses -1 to represent "true" and 0 to represent "false", and VARIANT_BOOL was designed to preserve this behavior.

like image 128
Davide Piras Avatar answered Dec 06 '22 14:12

Davide Piras


Because it is one.

VB6 bools are 16-bit values where 0 is false and any non-zero is true, but something set to true is set to -1 (0xFFFF). This way a lot of combinations of bools with numbers works well with VB6 because x AND TRUE gives x, x OR FALSE gives x, x AND FALSE gives FALSE and so on, with the same logic for bit-wise and boolean operators. Unfortunately it also means that 4 AND 2 is false despite that being TrueThing AND OtherTrueThing, so cautious VB6 coders didn't over-rely upon this, but used CBool to force the value to be either 0 or -1.

In general we have the choice of using natural machine size for the machine-processing speed versus using a single byte as it's the smallest addressable unit and hence gives a size advantage. Back when the natural-size on 16-bit machines was, well 16-bits of course, the balance went more in favour of going for the natural size than today when we've 32-bit and 64-bit machines. Visual Basic 1.0 ran on DOS and Windows 3.0 which could run on Intel 80286 16-bit processors, so it's not that strange a choice.

In the COM world, we have VARIANT_BOOL, which is just another way of saying "a bool, done the way VB6 does them", to allow for compatibility across langauges. The closest thing in C# would be either short or ushort, and if we cared only about C# we could pick either. Firstly though, we tend to use signed more than unsigned values, which would lean us toward short, but also ushort is not a CLS-compliant type, and there's hardly any point introducing an incompatibility with other .NET languages in obtaining compatibility with COM! Hence short is the clear choice.

like image 35
Jon Hanna Avatar answered Dec 06 '22 13:12

Jon Hanna