January 2015

Volume 30 Number 1


Visual Basic .NET - 14 Top Improvements in Visual Basic 14

By Lucian Wischik | January 2015

Visual Basic 14 is the newest version of Visual Basic, and it will ship as part of Visual Studio 2015. This version has been rewritten from scratch in about 1.3 million lines of VB code—earlier versions were actually written in C++. The team took advantage of the rewrite to rethink every part of VB from the ground up. I asked the team to pick out their top 14 improvements. They chose their favorites from across the board—in the coding experience, in the project system fundamentals and in the language itself.

Better Coding Experience

1. Refactorings “Just the fact that we finally get refactoring built directly into the product is huge.”—.NET MVP Jim Wooley

It used to be you had to buy add-on products just to get essential refactorings for Visual Basic, like extracting a method or inlining a temporary variable. There were a few refactorings for C#, and Microsoft had partnered with Developer Express to make its Refactor! add-in available to Visual Basic users since Visual Studio 2005. Now refactorings are built into Visual Studio 2015! To use them, click on an identifier, or highlight a sub-expression. Then hit Ctrl+Dot, or right-click and choose Quick Actions. This brings up a light bulb context menu of relevant actions, as shown in Figure 1.

Visual Basic 14 Now Has Built-in Refactoring
Figure 1 Visual Basic 14 Now Has Built-in Refactoring

Note that the refactorings are context-aware. For instance, if you extract the right-hand side of “Dim circleArea = Math.PI * radius * radius” out into a method, Visual Basic suggests the name “GetCircleArea” for that method. And it puts you into inline-rename mode if you want to change the name further. What’s smart about this inline-rename is that it can detect and warn you about name clashes if you pick a name that’s already in use, it can avoid clashes where possible, and it works across your entire solution, even changing names in C# projects, as well.

2. Analyzers “The feature is spectacular. I have so many ideas for how to use this feature ... all the little things I see in people’s code.”—Overheard from a Windows PowerShell MVP

Analyzers are a way to put those light bulbs, code actions and error squiggles into your own hands. You can use them to enforce coding guidelines throughout your team. If you’re flown in to debug a problem, you can plug in an analyzer to quickly find common code defects in the entire solution. And many of the libraries you use can become “code-aware” with their own built-in analyzers. For instance, suppose you haven’t yet used the Microsoft Azure Storage library or haven’t read articles on best practices. Because the library now comes with an analyzer that detects common pitfalls in use of its APIs, you can be immediately confident that you’re using it properly. It’s like having an expert code reviewer stand over your shoulder as you type.

You can add analyzers to your project under the new References | Analyzers node, (or via NuGet). Once there they become part of your project’s compilation—they run live as you type to show live error squiggles. They run when you build your project in Visual Studio or on the command line, and will even run on build servers. Analyzers get a chance to “crack open” the internals of the compiler, to look at the syntax trees of the project’s source code and its types and members. Developers are pleasantly surprised to discover how easy it is to code their expert domain knowledge into analyzers, thanks to these syntax trees and types+members. My favorite analyzer is one that detects where my team has been using Async Sub methods that should have been Async Function … As Task and issues a warning. This is a rough corner of asynchronous programming that not enough people are aware of, and it leads to difficult-to-catch concurrency bugs, so it’s great that my team can now catch the error at compile time. To get started writing your own analyzers, go to roslyn.codeplex.com.

3. No Need to Cursor off the Line “We do the right thing now.”—Dustin Campbell, Visual Basic Team Member

As a VB user, you’ve long been used to typing some code, then doing a quick “down-then-up cursor” to see if any error squiggles appear. Or you’d write code to fix an error squiggle, but then have to do the “down-then-up” for the squiggle to disappear.

Now you don’t have to go through all of that. Just leave the cursor where it is, and error squiggles will appear or disappear themselves.

4. References in XML Doc Comments “For people passionate about docs, this is an enormous step in the right direction.”—.NET MVP Sam Harwell

Are you passionate about XML doc comments? Here’s a small example:

''' <summary>
''' Similar to <see cref="List(Of Integer).Count"/>
''' </summary>
''' <param name="e">Thing to count</param>
''' <remarks></remarks>
Sub Count(e As IEnumerable)
End Sub

In previous versions of VB, when you typed out cref and param-name in your comments, you got completion-list help, but beyond that you were on your own. The compiler did some minimal validation to check that the names existed, but they were typeset in grey and not easy to find, look up or refactor.

Now in Visual Basic 14 the cref and param-name arguments are colorized properly. You can hover over them to see tooltips. When you do a rename-symbol refactoring (Ctrl+R, Ctrl+R), Visual Basic renames all references to a symbol, including those in cref and param-name. You can right-click on one of them and Go to Definition, or Find All References. If you want to refer to a method that has several overloads, you can now unambiguously refer to the single overload you want. These changes all make it easier to type references in your XML doc-comments—and get them right.

Project System Fundamentals

5. References Node in Solution Explorer “Fact is, we all have to tweak references daily.”—Lucian Wischik, Visual Basic Team Member

Figure 2 shows how a typical Visual Basic 14 project looks in Solution Explorer.

The References Node Is Now Shown in Solution Explorer
Figure 2 The References Node Is Now Shown in Solution Explorer

What’s new is the References node. This used to be hidden and you had to click Show All Files to see it—but that also showed lots of irrelevant files.

This previous behavior might have made sense 10 years ago when you’d start with a Windows Forms project and it would generally have the right set of references. But it’s a reality of modern development nowadays that the References node is used frequently—especially to manage NuGet references. It’s a small but handy convenience to be able to find it easily in Solution Explorer.

6. Shared Projects “This is really just nice tooling on top of linked files that makes them easier to work with.”—Windows Developer MVP Morten Nielsen

Suppose you want to share code between two or more projects. It’s a common-enough situation, for example when maintaining both Windows Presentation Foundation (WPF) and Windows Phone versions of an app. The goal is always the same: maximize code reuse, so, for example, a bug fix you make for one project will automatically benefit the other project.

In the past, you could choose between two techniques: use linked files to share common source code, or rearchitect your shared code into a Portable Class Library to share a common binary. Now Visual Basic 14 allows a third, powerful technique: Shared Projects.

Why would you use Shared Projects? The task of sharing code is deep and challenging with no good “one-size-fits–all” solution. Portable Class Libraries are a good, clean solution, but they force you to architect your code so the common code never calls into the WPF or Phone projects; it only calls into system APIs that are present on both WPF and Phone. Shared Projects are easier to use because they don’t require this rearchitecting.

To set up a shared project, right-click on your solution and select Add | New Project | VB | Shared Project. Next, right-click on each project’s Reference node in turn and choose Add | Shared Projects. A Shared Project is just a collection of the source files, XAML files, images and other assets that will be included in each project that references it.

For each of your projects you can also set up  My Project | Compile | Advanced Compile Options | Custom Constants with custom constants—WPF and PHONE, for example. Then, in your shared code, you can call into project-specific APIs like this:

#If WPF Then
  ' nothing needed
#ElseIf PHONE Then
  ShowBatteryStatus()
#End If

7. 50 Percent Faster Compile Times “50 percent is no joke.”—.NET MVP Sam Harwell

The Visual Basic compiler used to be written in C++. For Visual Basic 14, the team has rewritten it completely in VB, which has made it considerably faster! Here are two comparisons:

  • A large solution build (1.3 million lines of code) went from 68 seconds to 41 seconds.
  • A cold solution load (a Windows Store app) went from 6.7 seconds to 4.6 seconds

That’s a considerable time saving. It’s great when your mind can stay on track rather than meandering in the delay between “finish coding” and “press F5 to hit a breakpoint.”

The 50 percent performance increase might come as a surprise to people who think that C++ is faster than VB. The truth is that algorithms, data structures and concurrency are where you get real speed benefits. The performance boost from rewriting in VB comes from many places: rethinking the data structures; being able to express algorithms more cleanly and refactor more safely; using async and the threadpool; using the Visual Studio profiling tools to discover CPU and memory-allocation hotspots; and using analyzers to detect simple .NET performance gotchas like unnecessary boxing.

8. Lambdas and LINQ Expressions in a Watch Window “Awesome!”—Visual Studio Uservoice User Marco Senn-Haag

LINQ and lambdas are a great way to summarize data. One of the places this is needed most is at debug time, in the Watch and Immediate windows. In the past, any use of LINQ or lambdas here generated an error:

Evaluation of lambda expressions is not valid in the debugger.

Now, as you can see in Figure 3, it just works! For instance, if you’re at a breakpoint where you have a collection called “customers,” you can get a quick read on the collection by writing this in the watch window:

From c In customers Where c.OrderStatus = "Unfulfilled" Select c.LastName

Lambdas and LINQ Expressions in the Watch Window
Figure 3 Lambdas and LINQ Expressions in the Watch Window

Did you know you can use the Immediate Window without even launching your program? For instance, if you’ve just written a module with a function GetName, you can open the Immediate window (Debug | Windows | Immediate) and type “? GetName()” and it will evaluate.

Visual Studio 2015 will also have better support for Edit and Continue such as in Async and Iterator methods, as well as in more common situations like inside of and around LINQ queries and lambdas, even allowing you to add a new query or lambda expression to an existing method. Although this didn’t make it into the Visual Studio 2015 Preview, you’ll be able to do all of this in the final release.

9. Better Error List “The before and after really tell a great story.”—Visual Basic Team Member Anthony D. Green

The Error List in Visual Basic 14 has numerous practical improvements, ones that answer long-standing user requests (see Figure 4). Before, the Error List used to show fully qualified type names; now it shows only minimally qualified type names so you can more easily read the error message. And it shows the error code, as well, which is handy for sorting by error code. Even better, the error code is a hyperlink to an Internet search, often more useful than a link to the MSDN documentation page. Also, you can filter each column in the error list like you do in Excel.

The Error List in Visual Studio 2015 (bottom) is more Readable and Versatile Than in Visual Studio 2013 (top)
Figure 4 The Error List in Visual Studio 2015 (bottom) is more Readable and Versatile Than in Visual Studio 2013 (top)

Sometimes when making big changes it’s easy to get your solution into a state where a lot of downstream code is broken. In the past, VB would show only the first 101 errors. This made it difficult to get an idea of just how widespread the break was, or to get an overview of what kinds of changes you’d have to make. Now, Visual Basic 14 shows all errors without limit. (This can be configured under Tools | Options | Text Editor | Basic | Advanced | Show diagnostics for closed files.)

Language Improvements

10. Null-Propagating Operators “The constant need for null checking bites everyone both in productivity and in bugs.”—.NET MVP Deborah Kurata

Suppose you have a Customer class with an Address field that might legitimately be null, perhaps because your app doesn’t require addresses to be typed in. Previously, any code that needed to do something with the address—like display it to the user—would need to be safeguarded with null checking to take this into account. Such null checks quickly get tedious. With Visual Basic 14 you can elegantly handle the possibility of a null like this, using the new ?. operator:

Console.WriteLine("{0} ({1})",
  customer.Name,
  customer.Address?.Country)

The ?. operator is simply shorthand for the common but cumbersome pattern of assigning to a temporary variable and then checking for null:

Dim _temp = customer.Address
Console.WriteLine("{0} ({1})",
  customer.Name,
  If(_temp Is Nothing, Nothing, _temp.Country))

You can use ?. in a sequence and mix it with the regular dot operator, a?.b.c?.d, for example. It reads left-to-right. Any null value used by ?. will just stop the sequence short and give the answer Nothing, and any null value used by . will throw a NullReferenceException as usual.

The ?. operator is a null-conditional version of the . operator. There are null-conditional versions of most other operators, as well: indexing, array?(i); delegate invocation, delegate?(args); dictionary lookup, dict?!key; and XML axis properties, xml?.@attr, xml?.<key>, xml?...<key>.

You can use ?. in other handy ways, too:

If customer?.Age > 50 Then ...
' If branch taken only if customer is non-null AND is older than 50
Dim name = If(customer?.Name, "blank")
' Pick a default name if customer is null
Dim first = customers?.FirstOrDefault()
' Only invoke this method if customers is non-null

11. Multiline String Literals “Is it sad that I’m so excited for multiline string literals?”—Forum User Scaramouche

This is how you used to write multiline strings, peppered with vbCrLfs:

Dim json = "{" & vbCrLf &
"  'Name': 'Bad Boys'," & vbCrLf &
"  'ReleaseDate': '1995-4-7T00:00:00'," & vbCrLf &
"  'Genres': ['Action','Comedy']" & vbCrLf &
"}"

Understandably, a common request has been to allow string literals that span multiple lines. Now, in Visual Basic 14, you can:

Dim json = "{
  'Name': 'Bad Boys',
  'ReleaseDate': '1995-4-7T00:00:00',
  'Genres': ['Action','Comedy']
}"

A related noteworthy feature—also commonly requested—is that you can now put comments within multiline statements. Previously, they weren’t allowed inside LINQ expressions like the following:

Dim q = From x In y ' This is a from clause
        Where x < z ' And this is the where
        Select x    ' This select is redundant

12. String Interpolation “String interpolation makes for much simpler code, and makes the intent pop out.”—Channel9 User Judah

String interpolation is an easier way of writing strings with expressions in them, like so:

Dim s = $"hello {p.Name} you are {p.Height:0.00}m tall"

This is simply shorthand for the following:

Dim s = String.Format("hello {0} you are {1:0.00}m tall", p.Name, p.Height)

String interpolation is often easier to write than an explicit call to String.Format because it saves you having to juggle the positional placeholders {0} and {1}. And, of course, there’s full colorization and IntelliSense for the expressions inside the holes. String interpolation works particularly well with programmatic strings, as in these examples:

Dim fn = $"C:\Documents\{folder}\{file}.{ext}"
Dim url = $"https://{site}/{path}/{file}?search={query}"

As is normal for String.Format, this formats the string using the current culture. If you’re constructing a programmatic string that includes a floating point number, such as when you’re passing latitude and longitude to a Web service, you’ll most likely want InvariantCulture instead. This will be supported in Visual Studio 2015, but at press time the design wasn’t yet settled.

Note that string interpolation isn’t yet in Visual Studio 2015 Preview, but will be present in Visual Studio 2015 before it’s final.

13. NameOf “This will be such a help for so many scenarios I can think of.”—Roslyn Forum Member ewwloyd

The NameOf operator is a better way of embedding a string literal in your code, when that string literal refers to a name in your source code. Here’s one example:

Sub f(s As String)
  If s Is Nothing Then Throw New ArgumentNullException(NameOf(s))
End Sub

The NameOf operator isn’t evaluated at run time: It’s a compile-time constant, in this case the constant string “s.” The reason to use NameOf(s) is that it safeguards you against typos. For instance, if you rename the method parameter, then the NameOf argument will be renamed automatically. That wouldn’t have happened with just a string literal. Here’s another place where NameOf works well:

Private _age As Integer
Property Age As Integer
  Get
    Return _age
  End Get
  Set
    _age = Value
    RaiseEvent PropertyChanged(
      Me, New PropertyChangedEventArgs(NameOf(Age)))
  End Set
End Property

Note that NameOf isn’t yet in Visual Studio 2015 Preview, but will be present in Visual Studio 2015 before it’s final.

14. Open Source “We’re trying to engage the community. There are a lot of smart people out there. We’ll look at pull requests from the community just like we do our own ideas.”—C#/Visual Basic Architect Anders Hejlsberg

The final improvement is not in Visual Basic itself, but in the process of working with VB.

The source code of the VB compiler is now open source. So is the design process of the language itself. Each new feature proposal is made in the open, with full public scrutiny. The members of the Microsoft Visual Basic Language Design Team are essentially now stewards of the language. The team looks at proposals, considers them deeply, sees if there are unexpected gotchas or corner-cases, and determines if they meet the bar for inclusion in the language. The Language Design Meeting minutes are published openly. It’s truly an exciting time to be on the Visual Basic Language Design Team, and an exciting time to be a user of VB.

Wrapping Up

There are a lot of improvements in Visual Basic 14. This article has covered almost half of them. The general theme has been to make the existing VB work better in easy-to-use ways, without introducing difficult new concepts. For more information, check out roslyn.codeplex.com and blogs.msdn.com/vbteam.

This article refers to prerelease versions of Visual Basic 14 and Visual Studio 2015. All information is subject to change.


Lucian Wischik is on the Visual Basic/C# Language Design Team at Microsoft, with particular responsibility for VB. Before joining Microsoft he worked in academia on concurrency theory and async. He’s a keen sailor and long-distance swimmer. Reach him at lwischik@microsoft.com.

Thanks to the following Microsoft technical experts for reviewing this article: Dustin Campbell and Anthony D. Green
Dustin Campbell is a principal program manager on the Visual Studio team, where he works on the Visual Basic and C# IDE experiences. For the last five years, he has been focused on rebuilding the VB and C# compilers and IDEs as part of Project Roslyn.

Anthony D. Green is a program manager on the VB/C#/F# team at Microsoft who has been rewriting the VB & C# compilers (in VB and C#). Anthony has been programming in BASIC programming languages since age 14, mostly in QBasic and VB, and has been an impassioned member of the VB.NET community since 2004.