Category Archives: Visual Basic 2010

Collection initializer expressions

WARNING: This is a speculative post. Caveat emptor.

Well, I appear to be on a rhythm of about once a month posts, which seems OK for the moment. Moving on to another “future” topic, one of the most annoying things that we cut (at least, from my perspective) from VB 2008 was collection initializers. Collection initializers were a little different than the corresponding C# feature, because our plan was to introduce stand-alone initializers that didn’t have any intrinsic type. Instead the initializers “snap to” a particular type when they’re converted to it, just like lambdas and AddressOf expressions. For example:

' This works since VB 7.0!
Dim a() As Integer = {1, 2, 3, 4}
' This now creates a list.
Dim b() As List(Of Integer) = {1, 2, 3, 4}
' This assigns a new list to b.
b = {5, 6, 7, 8}

' If M takes Integer(), that's what it'll get. If it takes List(Of Integer), that's what it'll get.
M({1, 2, 3, 4, 5})

This is kind of nice, in that you can initialize collection types and arrays without having to state a type at all. We do the same trick C# does about looking for an Add method on a object that implements IEnumerable, so you can also use this syntax to initialize dictionaries:

Dim d As Dictionary(Of Integer, String) = {{1, "One"}, {2, "Two"}, {3, "Three"}}

All this is pretty straightforward, but there is some discussion about what type you should get if there is an absence of a target type. For example, assuming that local type inference is on, what should the following be typed as?

Dim x = {1, 2, 3, 4}

Our initial thought was that we should just infer the dominant type of the initializer and then create an array of that type. So the above example would type x as Integer(). And then the following:

Dim y = {{1, 2}, {3, 4}, {5, 6}}

Would infer a type of Integer(,), a two-dimensional array of Integer. With more nesting, you’d get more dimensional arrays. However, as we talked about it more, it seemed like maybe it might be more useful to infer List(Of T) for the 1-dimensional initalizer, Dictionary(Of K, V) for the 2-dimensional initializer, and nothing for more dimensions. So the type of x would instead be List(Of Integer) and the type of y would be Dictionary(Of Integer, Integer).

Both seem reasonable, so I’m curious what people would think. Remember, we will only fill in a type if we’re in a context (like type inference) where there’s no target type to use. We’ll always use a target type if there is one.

Implicitly implemented interfaces

WARNING: This is a speculative post. Caveat emptor.

This one is a little more speculative than the others, but it’s something that we’d like to get some feedback on. One complaint that we get from time to time has to do with interface implementation. A lot of people like the fact that there’s a nice explicit interface implementation syntax in VB, but sometimes it starts to feel, well, a little verbose. Even if you let the IDE create all the interface implementations for you, there’s still a lot of extra characters with all those “Implements IFoo.Bar”s, especially when the implementing method is the same name as the interface method.

One idea we’ve been kicking around is relaxing our rules to allow for implicit interface implementation. Today, when we’re checking interface implementation for some interface I1 what we do is:

  • Check to see if any base classes implement any of the members of I1. If so, we mark those methods as implemented.
  • Check to see if the current class implements any of the members of I1. If so, we mark those methods as implemented. If the current class implements a method that a base class implemented, the current class replaces that implementation.
  • If all of the methods of I1 are not implemented, we give an error.

What we would do is slightly modify the rules to:

  • Check to see if any base classes implement any of the members of I1. If so, we mark those methods as implemented.
  • Check to see if the current class implements any of the members of I1. If so, we mark those methods as implemented. If the current class implements a method that a base class implemented, the current class replaces that implementation.
  • If there are any methods of I1 that are not implemented, we check to see if there is a method with the same name and signature in the current class, and if there is, then that method implements the interface method.
  • If all of the methods of I1 are not implemented, we give an error.

What this would mean is that you could do something like this:

Class C1
    Implements IComparable(Of Integer)

    Public Function CompareTo(ByVal other As Integer) As Integer

    End Function
End Class

And not get any errors. There are a couple of things to note here if you’re familiar with C#, though. First, unlike in C#, if you declare a method in a derived class that has the same name as an interface method that is declared in a base class, you will still have to explicitly implement the interface method if you want the derived class method to take over. For example:

Class Derived
    Inherits Base
    Implements IComparable(Of Integer)

    ' Will not take over IComparable(Of Integer).CompareTo since Base already implements it!
    Public Function CompareTo(ByVal other As Integer) As Integer

    End Function
End Class

One could argue whether the derived class should or shouldn’t take over the implementation, but the bottom line is that if we allowed this we would be opening a potentially serious backwards compatibility problem. The above code could be written today (assuming Base implements IComparable(Of Integer)), and CompareTo will not take over the implementation of the interface. If recompiling your application in some future version of VB switched the implementation, this could introduce a very subtle and possibly very bad bug into your program. So it’s really a non-starter.

The other difference from C# is that we won’t search base classes for implicit interface implementations. For example, the following code would still give you an error:

Class Base
    Public Function CompareTo(ByVal other As Integer) As Integer

    End Function
End Class

Class Derived
    Inherits Base
    ' Error: IComparable(Of Integer).CompareTo is not implemented!
    Implements IComparable(Of Integer)
End Class

This can also be debated, but in the end we tend to err on the side of being more conservative-since Base didn’t implement IComparable(Of Integer) itself, it seems odd to pick it up when implementing the interface, as we have no way of knowing for sure that it’s really appropriate. There are also other highly technical issues relating to the mechanics of interface implementation that would make this situation complicated, especially if Base was in another assembly that we had no control over.

So the question is: would people find this useful? Annoying?

Automatically implemented properties

WARNING: This is a speculative post. Caveat emptor.

I apologize for the long silence, things have been a little busy around Panopticon Central these days! Anyway, I wanted to go back to talking about some of the things that we’re thinking about for the next version, and I thought I’d go over a small one: automatically implemented properties. As the name implies, these would be basically the same thing you get in C# 3.0’s auto-implemented properties.

What we’re talking about is allowing you to have a simple property declaration like so:

Public Property x() As Integer

This would generally expand under the covers to look something like this:

Private _x As Integer
Public Property x() As Integer
    Get
        Return _x
    End Get
    Set(ByVal value As Integer)
        _x = value
    End Set
End Property

The one major difference that we’re considering from C#’s auto-implemented properties is to allow initializers on the auto-implemented property. In other words, something like:

Public Property x As Integer = 10
Public Property y As New List(Of Integer)()

I think C# also doesn’t let you bind to the underlying field, but just like with other auto-generated stuff in VB, I think we’d err on the side of allowing you to bind to it if you really needed to. You can also make them Overridable if you like, to allow derived classes to provide their own implementation.

Just a little feature, but one that can be useful.

Implicit line continuations

WARNING: This is a speculative post. Caveat emptor.

One of the things that we’d like to address in the next version is line continuations. We know that they tend to annoy many developers who want to break their logical lines across multiple physical lines, and we’ve gotten many requests to get rid of them altogether. Unfortunately, there’s a reason we haven’t just dropped them–they actually are needed in certain scenarios. For example, take the following contrived example:

    Sub Main()
    End _
    Sub

If I remove the line continuation, I’ll now get a compile error because “End” now is the “End” statement, and the Sub looks like it’s trying to start a new subroutine in the middle of the current subroutine. There are quite a few of these syntactic ambiguities sprinkled throughout our grammar, some of which might be quite obscure and unnoticed until someone’s code actually broke. So instead of taking a maximalist approach and trying to remove the line continuation everywhere, we’ve been thinking about a more minimalist approach and looking at where removing the line continuation might be most useful. This produced a much more tractable list of places where we might productively remove the line continuation. In particular:

  1. After binary operators in expression contexts. Note that this does not include assignment operators. For example:
    a = b +
        c
  2. After the following punctuators: comma (“,”), open parenthesis (“(“), open curly brace (“{“), begin embedded expression in XML (“<%=”). For example:
    Console.WriteLine(
        "{0} {1}",
        FirstName,
        LastName)
    
  3. Before the following punctuators: close parenthesis (“)”), close curly brace (“}”), end embedded expression in XML (“%>”). For example:
    Console.WriteLine(
        "{0} {1}",
        FirstName,
        LastName
    )
  4. After an open angle bracket (“<“) in an attribute context, before a close angle bracket (“>”) in an attribute context, and after a close angle bracket in a non-file-level attribute context (i.e. an attribute that does not specify “Assembly” or “Module”). For example:
        <
            Conditional("Foo"),
            Conditional("Bar")
        >
        <
            Conditional("Baz")
        >
        Sub Main()
        End Sub
    
  5. Before and after query expression operators. For example:
    Dim ys = From x In xs
             Where x > 5
             Select
                ten = x * 10,
                twenty = x * 20,
                thirty = x * 30

One thing that is not currently on the list is allowing an implicit line continuation after a dot, so you couldn’t break up “a.b.c” implicitly. It’s not that we can’t do dot, just that it’s quite a bit more expensive and problematic for Intellisense. We’d be interested to hear if this is something people really want to/need to do, or if it’s just a nice-to-have.

Are there any other places that we missed that you can think of?

Lang .NET 2008, Scripting, and Visual Basic

WARNING: This is a speculative post. Caveat emptor.

Several weeks ago, I gave a presentation entitled Bringing Scripting (Back) to Visual Basic at the Lang .NET 2008 conference. A video of the presentation has now been posted, so you can check it out for yourself. (The presentation was also covered by EWeek in an article entitled Bringing Sexy Back to Visual Basic.)

The main theme of the presentation is the same one I’ve been talking about on and off over the past year or two: moving Visual Basic back towards it’s scripting roots. The main thrust of this presentation was the technical side of the story–namely, what we would need to do to the existing Visual Basic compiler to be able to effectively use it as a scripting engine. The presentation talks some about the way the compiler is structured, how it might change and some of the things were thinking about enabling. In particular, what we’d like to see is not just that Visual Basic can be embedded anywhere, but that all the services that the compiler provides–parsing, semantic analysis, code generation–are available to be used by any program that needs them. The DLR is a key part of this, but there’s a lot of work on top of that.

I also showed some fun demos of some prototypes that we’ve whipped up using our current codebase. Nothing we’re committing to at the moment, but it gives you some of the flavor of what we’re thinking about.

One thing this presentation didn’t cover (and which Ted Neward brought up in the Q&A afterward) is what we might do to the language itself to make it more scripting-friendly. That’s an area where things are less well-defined and even more speculative than what I talked about, so I left it out for now. Maybe soon I can talk more about it…

The big "D"-word

WARNING: This is a speculative post. Caveat emptor.

I know that I’m running a great risk of touching the third rail of the VB community by even speculating about this, but it seems like the right time to have a bit of a conversation about the big “D”-word.

That is, deprecation.

Yes, deprecation. Now before anyone starts freaking out, foaming at the mouth or writing a petition, let me emphasize that my thinking along these lines is entirely within the guidelines discussed in the language specification, which mandates a long and gradual process of deprecation that involves continuing to support the deprecated feature for a reasonable period of time. The guidelines also state in part:

…feedback must be solicited from the user community on deprecation of the feature and full notice given before any final deprecation decision is made. The deprecation process may be reversed or abandoned at any point based on user community feedback.

So I’m really just floating some personal trial balloons here. After all, it’s now been almost three major releases since the big move to .NET, and I think it’s started to become clear that some of the features we carried forward are a bit, uh, underused. In the interest of paring down the language specification just a bit in it’s inevitable march towards more and more pages, I’ve been pondering the question: “If I was going to deprecate parts of the language that don’t seem to be used, what would I deprecate?” I’ve come up with a few candidates that seem pretty safe:

  • Type characters. Yes, we still allow you to say “Dim a$”. So far as I have ever seen, no one uses them anymore. It would be nice to reclaim a bunch of characters at some point in the future, and it would be relatively easy to include error corrections to fix this up.
  • Copying of boxed value types. I’m not even sure I could explain this in a bullet point. If you read section 8.6 of the language spec, Value Type Conversions, it’ll discuss this a little more detail. I think this is counterintuitive behavior for most people and is incomplete in any case. The only real question here is: are there programs that depend on this behavior? We’d need to think/talk a lot more about it before we could even consider this one.
  • Mid$() assignment. Bet you didn’t know you could even do this, did you? See section 10.6.3 in the language spec for more on this.
  • End statement. I’m curious if this one is still used by people, especially now that most frameworks like WinForms and WPF have Application objects that have a proper Exit/End method. If this one is popular, it might not fly as deprecatable.
  • Erase statement. I’ve found that ReDim is actually still fairly useful as a shorthand way to redimension an array. However, Erase is completely useless–you could just replace it with an assignment to Nothing and you’d get the same thing.
  • REM comments. Bet you didn’t know you could even do this one either, did you? There’s something nostalgic about it (Erik Meijer loves them), but, really, who uses them anymore?

You’ll note that I’m only including things here that I think are truly not used much or not useful. There are things I think some people would like to see disappear (like, say, On Error), but are still being used heavily enough to make them be not reasonable candidates.

I’m curious what’s people’s feelings about this are. Does this just bring up bad memories? Are there other candidates you’d throw on the list? As I said, at this point, I’m just talking. Depending on the reaction, the next step would be to look a little more formally at it in the team…

What’s on my mind for VB10 (and yours?)

WARNING: This is a speculative post. Caveat emptor.

Last week, one of the VB MVPs asked on a private alias what our thinking was about VB10. As I kind of indicated in my previous entry, I don’t think we have a clear idea yet of what’s going to be on the table for the next rev-VB 2008 was kind of an aberration in that LINQ was in gestation long before VB 2005 even shipped. But I can say what’s at least on my mind:

  • Hosting or, more generally, opening up the compiler services to the outside world.
  • Decreasing lexical “noise” when looking at VB code.
  • Increasing the extensibility of the language so that it takes less work to extend the language and can be done by libraries (Ruby is an example of what I’m thinking of here, but only a general example).
  • Addressing UNDONE tasks from Orcas (object initializers, statement lambdas).
  • Addressing persistent annoyances (line continuations is a good example here).
  • Addressing whatever else comes up from the community as we release VB 2008.

I know that I’ve already added the usual caveats above, but I want to make double clear this is just what’s on my mind at the moment-in other words, things that I’m personally thinking about. These are not official team priorities, planned for the next rev, or anything like that. The next version could look radically different than the list above. I should also add that I mostly think about the language, so that’s why this list doesn’t talk about the IDE.

I’d be interested (in keeping with the last bullet point) what people might be specifically in for the next release. What’s at the top of your list these days?