Question

The following code works fine in C#.

    Int32 a, b;
    Int16 c;

    a = 0x7FFFFFFF;
    b = a & 0xFFFF;
    c = (Int16)b;

But this code crash with a OverflowException in VB.NET.

    Dim a, b As Int32
    Dim c As Int16

    a = &H7FFFFFFF
    b = a And &HFFFF
    c = CType(b, Int16)

Both code snippets seem the same to me. What is the difference and how can I get the C# code converted to VB.NET?

Was it helpful?

Solution

From MSDN:

For the arithmetic, casting, or conversion operation to throw an OverflowException, the operation must occur in a checked context. By default, arithmetic operations and overflows in Visual Basic are checked; in C#, they are not. If the operation occurs in an unchecked context, the result is truncated by discarding any high-order bits that do not fit into the destination type.

EDIT: If you're going to port code from C# to VB.NET, you may be interested in differences between them. Also compare and explicitly set compiler settings to be the same as default settings in C# (when needed).

OTHER TIPS

First up: My understanding of this is that CType(b, Int16) isn't the same as (Int16)b. One is a conversion of type (CType) and the other is a cast. (Int16)b equates to DirectCast(b, Int16) rather than CType(b, Int16).

The difference between the two (as noted on MSDN) is that CType succeeds so long as there is a valid conversion, however, DirectCast requires the run-time type of the object to be the same, and as such, all you're doing is telling the compiler at design time that this object is of that type rather than telling it to convert to that type.

See: http://msdn.microsoft.com/en-us/library/7k6y2h6x(VS.71).aspx

The underlying problem though is that you're trying to convert a 32 bit integer into a 16 bit integer which is... [I'm missing the word I need, perhaps someone can insert it here for me] lossy. Converting from 16 bit to 32 bit is allowed because it's lossless, converting from 32 bit to 16 bit is undefined. For why it works in C# you can see @Roman's answer - it relates to the fact that C# doesn't check the overflow.

The resulting value of &H7FFFFFFF And &HFFFF results in UInt16.MaxValue (65535) UInt16 runs from 0 to 65535, you're trying to cram that into Int16 which runs from -32768 through to 32767 which as you can see isn't going to work. Also the fact that this value might fit into a UInt16 is coincidental, adding two 32 bit integers and trying to cram them into a 16 bit integer (short) would frequently cause an overflow and thus I would say this is an inherently dangerous operation.

Have you tried using DirectCast(b, Int16)? CType is not the same as a C# cast.

Here's an article comparing the performance of DirectCast and CType, as well as going into more detail to when either should be used.

http://www.cnblogs.com/liujq007/archive/2010/12/04/1896059.html

Summary:

To unsigned type: just do And operator, or 2st method.

Dim a As Byte = CByte(300 And &HFF)

To signed type: left shift n bits, then right shift n bits, which is to expand the signed bit. n = (sizeof(type1) - sizeof(type2)) * 8 or VB:use Len(New type) instead of sizeof(type)

Dim a As Short = CShort(34042 << 16 >> 16)

You can find the details from the link below.

?CType(b, Int16)
Constant expression not representable in type 'Short'.

?b
65535

?directcast(b, Int16)
Value of type 'Integer' cannot be converted to 'Short'.

?int16.TryParse(b.ToString(), c)
False

You can truncate this kind of overflow with a structure.

<StructLayout(LayoutKind.Explicit)> _
Public Structure int3216
    <FieldOffset(0)> Public i32 As Int32
    <FieldOffset(0)> Public i16high As Int16
    <FieldOffset(2)> Public i16low As Int16
End Structure

...

  Dim _i3216 As int3216
  _i3216.i32 = a And &HFFFF
  c = _i3216.i16low

I came across this question when looking for a solution for converting a Short and getting the overflow result with out the overflow error. I found a solution here:

http://bytes.com/topic/visual-basic-net/answers/732622-problems-typecasting-vb-net

about halfway down the page is this:

The old, VB "Proper" trick of "side-stepping" out to Hexadecimal and back again still works!

Dim unsigned as UInt16 = 40000
Dim signed as Int16 = CShort(Val("&H" & Hex(unsigned)))

it seems to work pretty slick!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top