Req6: Better casting

[This post is part of a series, "wish-list for future versions of VB"]


IDEA: Casts should flow from left to right. Here are some candidate syntaxes:

    Dim x1 = (HtmlPage.Document.GetElementsByTagName("a").First As HtmlElement).Children(0) As HtmlElement

    Dim x2 = HtmlPage.Document.GetElementsByTagName("a").First.DirectCast(HtmlElement).Children(0).DirectCast(HtmlElement)

    Dim x3 = HtmlPage.Document.GetElementsByTagName("a").First.CType(HtmlElement).Children(0).CType(HtmlElement)

    Dim x4 = HtmlPage.Document.GetElementsByTagName("a").First.CTypeDynamic(HtmlElement).Children(0).CTypeDynamic(HtmlElement)

    Dim x5 = HtmlPage.Document.GetElementsByTagName("a").First.Cast(HtmlElement).Children(0).Cast(HtmlElement)

The current code "y1" looks awkward because it doesn't flow from left to right (and likewise with C++ style casts "y2"):

    Dim y1 = DirectCast(DirectCast(HtmlPage.Document.GetElementsByTagName("a").First, HtmlElement).Children(0), HtmlElement)

    Dim y2 = (HtmlElement)((HtmlElement)HtmlPage.Document.GetElementsByTagName("a").First).Children(0)


The "As" would mean the same as DirectCast. The "Cast()" operator mean... I'm not sure! It would be shorthand for DirectCast or CType or CTypeDynamic, but it's not obvious which!


IDEA: Casts should use the type of their context to avoid typing. For example:

        Dim y = "1"

        Dim x As Integer = CType(y)  ' infers CType(y, Integer) because of the context




Casting is more difficult than it appears. Eric Lippert wrote a great blog post on the C# casting operator. As an example the C# cast "(string)expr" does three opposite things:

  1. Sometimes "expr" has compile-time type Object, for example, but you know it's really a String, and you use a cast to tell this to the compiler. DirectCast and C# as do this and only this.

  2. Sometimes "expr" has compile-time type Char(), for example, and you're asking the compiler to find at compile-time conversion to turn it into a String. CType does this and the previous one.

  3. Sometimes "expr" has compile-time type Object, for example, and you don't know what it really is, but you're asking the runtime to look at the runtime type of "expr" and look for any user-defined conversions to that can turn it into a String. CTypeDynamic and the C# cast operator do this and the previous two.


Provisional evaluation from VB team: Flowing the casts from left to right is a decent idea. The fact that there are so many different meanings for casts make it difficult to use "As" or ".Cast()", but the other possibilities (.CType(), .DirectCast(), ...) look plausible. However, you can already do a pretty decent job with extension methods:

    <Extension()> Function [CType](Of T)(ByVal x As Object) As T

        Return CType(x, T)

    End Function


    Dim y = "1"

    Dim x = y.CType(Of Integer)()

 As for the idea of using context -- it doesn't improve readability. It would be better to just write "Dim x = CType(y,Integer)".


Comments (4)

  1. Kevin Ryall says:

    I don’t like the second idea – it just seems less clear.  

    Flowing casting from left to right looks interesting though – it’s like a fluent API (I’ve got into those in big way recently), and just seems to read more naturally.

  2. Kyralessa says:

    I like the .Cast or .DirectCast syntax.  I’ve never cared for CType; it’s just an ugly keyword.  I’d be glad to have it go away in favor of some new syntax.

  3. Strilanc says:

    @VBTeam: Extension methods don’t work on Object, which is a pretty big deal for casts.

  4. Mark Hurd says:

    Yep, built in "extension" method versions of CType, DirectCast and even TryCast that DOES work on Object and the Of is possibly optional or, given these aren't going to be like normal extension methods, drop the Of.

Skip to main content