Conversion operators in VB

In my entry on “native” languages on the CLR, I made a blanket statement that the intrinsic VB conversion operators would be faster than the conversion functions in the Convert class because they compile down to IL rather than function calls. In my quest to emphasize my point, however, I made a serious misstatement which was not intentional but should be corrected. Not all intrisic operators compile down to simple IL instructions, although most do so. And the ones that don’t are worth discussing. So let me spend a moment talking about conversions.

The intrinsic conversion operators (CObj, CByte, CShort, CInt, CLng, CDec, CSng, CDbl, CDate, CStr, CChar, CType, DirectCast) generally fall into several broad categories of implementation:

  1. Conversions that are pure IL statements. The best example here is the conversion from Integer to Long or Long to Integer. This compiles directly down to a conv.i8 or conv.i4.ovf instruction, respectively. You really, really, really don’t want to be calling functions to do this kind of conversion unless you’ve got a lot of faith in inliners, which I generally don’t.
  2. Conversions that are mostly pure IL statements. The best example here is the conversion from Double to Integer. This compiles down to a call to Math.Round and then a conv.i4.ovf instruction. The purpose of the extra call is to implement banker’s rounding, which the CLR doesn’t natively support. (In banker’s rounding, a decimal number equidistant between two whole numbers is rounded to the nearest even number. So 3.5 rounds to 4, but 2.5 rounds to 2.) In this case, calling Convert.ToInt32(Double) is not the same as CInt(Double), and you have to choose which semantic you desire.
  3. Conversions that are calls to the Convert class. The Decimal type is not natively supported by the CLR. As such, conversions to and from Decimal (with the exceptions listed below) turn into calls to Convert.ToDecimal() or the appropriate helper. There’s no point in us reimplementing the conversion since it’s the same for both the CLR and VB. In this case, calling Convert.ToDecimal(Integer) is exactly the same as CDec(Integer).
  4. Conversions that call VB specific helpers. There are only two cases that fall into this category: conversions to and from String, and conversions from Object.
    • Conversions to and from String call VB specific helpers because VB does a variety of extra things for you. For example, when converting String to Integer, we’ll parse decimal numbers and do the appropriate rounding. So while Convert.ToInt32(“10.5“) will barf with an exception, CInt(“10.5“) will work just fine. And this is just one example of the nice stuff that we’ll do for you. As always, though, extra functionality can equal extra cost. So if you just want the very basic functionality that Convert.ToInt32() calls (or you prefer calling two functions), you might get slightly better performance by calling it instead of using CInt on a String.
    • Conversions from Object call VB specific helpers because VB needs to be able to implement VB specific semantics (such as the String conversions and banker’s rounding) when converting values from one type to another. For example, Convert.ToInt32(CObj(“10.5“)) still throws an exception, while CInt(CObj(“10.5“)) won’t.

One interesting thing to note is that if you really want only the CLR conversions and nothing else, the DirectCast operator will turn off most of the VB-specific conversion features (I believe we still do banker’s rounding, though). Then you can call the Convert class methods when you run into conversions that DirectCast doesn’t support. I still think that this is an extreme way to go about things, but I know some people are just that way. Me, I use the regular VB operators and then look out for performance sensitive areas where I might need something different.

27 thoughts on “Conversion operators in VB

  1. Kevin Harder

    Paul,

    Very informative post, thank you. This is my first post on your blog, but I am a long time reader – this is one of the few informative/useful VB.NET-centric web logs I’ve found. Great job!

    Anyways, I had a question regarding where the CType() function in VB.NET falls into your above categories. Does CType() translate directly to the VB-specific conversion functions such as CInt(), or is it the same as using Convert.ToInt32. or something entireley different? There’s been some discussion at my work in regards to CInt vs CType(obj, Int32) usage [and other datatypes as well].

    Kevin

    Reply
  2. Christopher Hawkins

    "Me, I use the regular VB operators and then look out for performance sensitive areas where I might need something different."

    What kind of performance drag can the regular VB operators cause? It has never even occurred to me to use anything else (although I am new to VB.NET and admittedly haven’t mastered all the nuances of squeezing maximum performance from the language and framework).

    Reply
  3. paulvick

    Thanks for all the good comments!

    Maxim: I like it!

    Kevin: CType and the other operators are completely equivalent. So CType(x, Int32) is exactly the same as CInt(x).

    Christopher: For example, the extra work we do converting strings to integers might not be necessary in your app. If there is a conversion from string to integer that happens a huge amount, the extra overhead might make a difference. But I would really only use alternatives if you’ve proven there’s a performance issue in your app.

    Reply
  4. Christopher Hawkins

    Paul: OK, I get what you’re saying. Great article. I’m going to crib from your work liberally next time I have to do a white paper that has anything to do with type conversions. ;)

    Reply
  5. Beth Massi

    I use DirectCast a lot when casting objects down an inheritance chain.

    Dim c As Control

    …..

    If TypeOf c Is MyControl Then

    DirectCast(c, MyControl).DoSomethingCool()

    End if

    Is it better to use CType instead in this situation?

    Reply
  6. paulvick

    Beth: No, you’ll get exactly the same behavior in the case where you are casting down the inheritance hierarchy unless you are casting from Object. In that case, you lose extra features using DirectCast but can gain extra performance.

    Reply
  7. Pingback: Dave Donaldson's Blog

  8. Pingback: VS Data Team's WebLog

  9. Pingback: VS Data Team's WebLog

  10. JA

    I wonder how Val("10.5") compares to CDbl("10.5"). One difference is that Val("10.5XYZ") does produce 10.5R instead of an exception.

    Reply
  11. Santhosh Aravindh

    Wat is the Replacement of CType function in VB 6

    rather how can i implement CType function in VB 6???

    Can anyone help me…..

    Thx in Advance,

    Santhosh

    Reply
  12. Dave

    I get a ‘cannot convert from string to double’ error with the line in the following FOR loop. I’ve tried ceaseless combinations to no avail. Any ideas?

    For Each m As Match In re.Matches(dataLine)

    dblArr(i, j) = CDbl(m.Value)

    Next

    Reply
  13. hetal akruwala

    i would like to have infomation or help regarding vb source code or script for how to convert total sum into textual description or words in a vb textbox on a form.

    my email is achichu@yahoo.com. do provide me with the source code information. i have tried a lot. and i have to give exam.

    thank you.

    Reply
  14. MNT77

    i have a usercontrol with datagridview inside and i’d like to obtain datagridview with a cast, there is a way to do it without inherit from datagridview?

    Thanks

    Reply
  15. Knigit

    Is there a way to disable "Bankers Rounding" in visual basic. I can set the project properties to explicit to force me to cast all math, but then I would use C++, not visual basic for the program.

    Example:

    Dim iValue as integer

    iValue=5.8

    Now iValue should equal 5 not 6.

    I could code it

    iValue=int(5.8)

    to get the correct behaviour but this is a pain

    Reply
  16. EMERSON

    Hi PPL,

    I will ask you a simple question..but if you have a solution you’re a genius!!

    So… if i write in coding this:

    Dim sStr As String

    sStr = 5 + 5 * 3

    sStr will become 20

    But how can I have the answer of that formula stored in variable sStr IF THE FORMULA IS INPUTTED IN A TEXTBOX???????

    Reply
  17. Jeff Tomaski

    I have done a lot of research and tried the CInt – CObj syntax on my String to Integer conversion and it still errors out as an Invalid conversion format.

    Can someone please help. I am a new VB.Net programmer and need this code to run. Many thanks,

    Jeff Tomaski

    <%@ Page Language="VB" MasterPageFile="~/pts3.master" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="Proj_Active_Default" title="Untitled Page" %>

    <script runat="server">

    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)

    Session("DateCount") = LblDateCount.Text

    Session("MNTCount") = LblMNTCount.Text

    Session("PACCount") = LblPACCount.Text

    If Not (Session("DateCount") Is Nothing) Then

    Dim vDateCount As Integer = CInt(CObj("DateCount"))

    End If

    If Not (Session("MNTCount") Is Nothing) Then

    Dim vMNTCount As Integer = Session("MNTCount")

    End If

    If Not (Session("PACCount") Is Nothing) Then

    Dim vPACCount As Integer = Session("PACCount")

    End If

    If "DateCount" < 10 And "MNTCount" < 2 And "PACCount" < 2 Then

    Response.Redirect("SiteInfo/SiteHome.aspx")

    Else

    Response.Redirect("Dell2950_CountError.aspx")

    End If

    End Sub

    </script>

    <asp:Content ID="Content1" ContentPlaceHolderID="ContentPH1" Runat="Server">

    <asp:SqlDataSource ID="Sql_Mon_Wed_2007" runat="server" ConnectionString="<%$ ConnectionStrings:pts3Connection %>"

    SelectCommand="SELECT * FROM [A_Mon_Wed_2007]"></asp:SqlDataSource>

    <br />

    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox><br />

    <asp:Label ID="LblDate" runat="server" Text="Label"></asp:Label><br />

    <asp:SqlDataSource ID="Sql_DateCountBySite" runat="server" ConnectionString="<%$ ConnectionStrings:pts3Connection %>"

    SelectCommand="SELECT COUNT(sSiteCode) as DateCount&#13;&#10; FROM dbo.P_Dell2950&#13;&#10;WHERE ([start_time] = @start_time)">

    <SelectParameters>

    <asp:ControlParameter ControlID="TextBox1" Name="start_time" PropertyName="Text" />

    </SelectParameters>

    </asp:SqlDataSource>

    <asp:SqlDataSource ID="Sql_DateCountByMNT_tz" runat="server" ConnectionString="<%$ ConnectionStrings:pts3Connection %>"

    SelectCommand="SELECT COUNT(sSiteCode) AS MNT_TZ FROM dbo.P_Dell2950 WHERE (start_time = @start_time) AND (mountain_tz = ‘Y’)">

    </asp:SqlDataSource>

    <asp:SqlDataSource ID="Sql_DateCountByPAC_tz" runat="server" ConnectionString="<%$ ConnectionStrings:pts3Connection %>"

    SelectCommand="SELECT COUNT(sSiteCode) AS PAC_TZ FROM dbo.P_Dell2950 WHERE (start_time = @start_time) AND (pacific_tz = ‘Y’)">

    </asp:SqlDataSource>

    &nbsp;

    <asp:Label ID="LblDateCount" runat="server" Text=’<%# Eval("DateCount") %>’ Visible="false"></asp:Label>

    <asp:Label ID="LblMNTCount" runat="server" Text=’<%# Eval("MNT_TZ") %>’ Visible="false"></asp:Label>

    <asp:Label ID="LblPACCount" runat="server" Text=’<%# Eval("PAC_TZ") %>’ Visible="false"></asp:Label><br />

    <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />

    </asp:Content>

    Reply
  18. ccy

    hi PPl….

    i would like ask you a simple question..

    if i write in coding this:

    Dim sStr As String

    sStr = (11 / 5) * 2)

    sStr will become 4.4 but i want the answer sStr = 5…

    so what is the solution???? thanks…

    Reply
  19. Pingback: Anonymous

  20. Pingback: Anonymous

Leave a Reply