SharpDevelop Community

Get your problems solved!
Welcome to SharpDevelop Community Sign in | Join | Help
in Search

VB CInt() convert to C# is an int cast but should be Convert.ToInt()

Last post 03-05-2008 4:50 AM by harrystein. 2 replies.
Page 1 of 1 (3 items)
Sort Posts: Previous Next
  • 03-04-2008 1:37 PM

    VB CInt() convert to C# is an int cast but should be Convert.ToInt()

    Running 2.2 I see this issue (and assume it remains with latest build as 'Search' does not show any results).

    CInt() is converted by SharpDevelop 2.2 to a simple int cast, which is plan and simply wrong.

    By the way, if you Google around, this notion of the equivalent of CInt() being an (int)  cast in C# is proliferating.  Hopefully this report will put a stop to it.  And I assume I am correct but welcome rebuttals -- the argument which follows should be compelling enough.

    The (int) cast operator in C#, like in C and C++, does a simple truncation  Thus (int)(3.5) is 3 and (int)(4.5) is 4.  But Visual Basic (and VB .NET) CInt() does rounding -- and while I have no comment on VB6's rounding behavior (TBD, don't really care), I do know for a fact that VB .NET uses banker's rounding for CInt().  Banker's rounding says that when the the fractional part of a "real" type (types like float, single, double, Single, Double, Decimal) is exactly 0.5, the integer conversion functions such as CInt() will round the number to the nearest even integer.  The MSDN examples always given is 0.5 rounds to 0, 1.5 and 2.5 both round to 2.  And they remind us this is sometimes called "banker's rounding" and "its purpose is to compensate for a bias that could accumulate when adding many such numbers together."

    Having said all of that, the SharpDevelop convert of CInt(x) to (int)x is wrong.  The correct conversion should be Convert.ToInt(x) since the C# standard states this member function (and that of all the integral convert member functions such as Convert.Int16, Convet.Int32, etc.) convert with banker's rounding whenever the argument is of type Decimal, float, or double.

    This is clearly an important and nuanced math conversion that will bite and add a few more gray hairs to to (perhaps, IMHO) more than a few people. 

    You can easily verify this using Visual Studio :- ) as a goldenrod and taking any compiled vb and c# project/solution and invoking the Immediate window and doing:

    ? CInt(3.5)                    in the VB .NET project's immediate window -- result will be 4

    ? (int)(3.5)                    in the C# .NET project's immediate window -- result will be 3 (not same as VB)

    ? Convert.ToInt(3.5)       in the C# .NET project's immediate window -- result will be 4 (correct)

  • 03-04-2008 4:19 PM In reply to

    Re: VB CInt() convert to C# is an int cast but should be Convert.ToInt()

    This is a known bug.

    BTW, what should the other direction convert to?

    C# (int)a -> VB CInt(Math.Floor(a)) ? Is that correct, or is there a better solution?

    Daniel Grunwald
  • 03-05-2008 4:50 AM In reply to

    Re: VB CInt() convert to C# is an int cast but should be Convert.ToInt()

    Recall the cast (int)(expr ) is the wrong answer for VB CInt(expr ) to C#  -- i.e, should be
    Convert.ToInt32(expr ) .  Still, to answer the question, the following types for expr can be specified for the explicit cast to int (more to come :-) ):

    (int)(long_expr)
    (int)(ulong_expr)
    (int)(float_expr)  
    (int)(double_expr)
    (int)(decimal_expr)


    So, assuming (a) you see the explicit int cast operator (p.s., this email does not at all deal with the many other casts one would have to deal with -- sounds like a monumental effort :-(), and (b) you know the type of the expression being cast is one of the five types shown above, then I would only be able to answer one or two of them -- the rest require more research and thought and fiddling around in the C#, VB.NET specs and the immediate window in Visual Studio to see what Microsoft does:

    (int)(long_expr)             Fix(   (Long)(long_expr)   )
    (int)(ulong_expr)           Fix(   (ULong)(ulong_expr) )
    (int)(float_expr)             Fix(   (Single)(float_expr)   )
    (int)(double_expr)         Fix(   (Double)(double_expr)   )
    (int)(decimal_expr)       Fix(   (Decimal)(decimal_expr)   )

    I didn't mention the aliased types line System.Int16, System.Byte -- these are all aliased to the known numeric types that also have to be dealt with in the manner shown above.  These include sbyte, byte, short, ushort, char and (maybe?) bool.  I assume (not verified) each and every one of these can be cast to an int in C# -- and thus have an equivalent type in VB

    C# Type/VB.NET Type

    Aliased Type

    sbyte/SByte    System.SByte
    byte/Byte System.Byte
    short/Short  System.Int16
    ushort/UShort  System.UInt16
    int/Integer  System.Int32
    uint/UInteger  System.UInt32
    long/Long    System.Int64

    ulong/ULong 

    System.UInt64

    char/Char 

    System.Char
    float/Single   System.Single
    double/Double    System.Double
    bool System.Boolean
    decimal/Decimal System.Decimal

    The corresponding VB type is shown in red and came from either a PrimitiveTypeName  of  Char  (To-Be-Verified) or the one of the NumericTypeNames of   Byte  |  SByte    |  UShort  |  Short  |  UInteger  |  Integer  |  ULong  |  Long    |  Single   |  Double    |  Decimal

    That's all I know.  Like everything else, it's a little of details and not a trivial task!

    Regards,

    Harry

Page 1 of 1 (3 items)
Powered by Community Server (Commercial Edition), by Telligent Systems
Don't contact us via this (fleischfalle@alphasierrapapa.com) email address.