Introduction to Visual Basic 9.0 Features

Alright, so I've spent a lot of my time this summer (and more this fall) going to various groups and talking about the features in C# 3.0.  This is something of a thorn in the side of my good friend Cory Smith, who despite the fact that he is a "Visual Developer" MVP, is the staunchest Visual Basic advocate that I'm aware of.  I swear this man dreams VB, I know he blogs VB over at AddressOf.com.  As such, I thought it was time to give all of my friends who prefer Visual Basic their fair time, or at least some time, so this post details the new features and shows the syntax for things.  There is not exact parity to the C# feature list, but its a close thing, so here we go. Automatic Properties We'll start of with the biggest exclusion.  VB does not get automatic properties, so they are left with the more verbose version of the syntax. Partial Methods Partial Methods are very useful for light weight event handling in generated code.  For instance, lets assume that you had a generated class that looked like this: Partial Class NewFeaturesPartial Private Sub BeforeTextChange(ByVal oldText As String, ByVal newText As String)End Sub Partial Private Sub AfterTextChange(ByVal oldText As String, ByVal newText As String)End Sub Private _text As StringPublic Property Text() As StringGetReturn _textEnd GetSet(ByVal value As String)BeforeTextChange(_text, value)_text = valueAfterTextChange(_text, value)End SetEnd PropertyEnd Class The partial methods BeforeTextChange and AfterTextChange are convenient extension points should the person using your generated code needs to hook into them, but the magic is that any of these methods which are not given implementations (both in our case above) get compiled away.  On the right you can see the Reflector disassembly for Text property.  Note that there are no calls to the partial methods, because the compiler did not emit IL for them since there were no implementations.Now let's add the following short code-snippet into our project:Partial Class NewFeaturesPrivate Sub BeforeTextChange(ByVal oldText As String, ByVal newText As String)newText += oldTextEnd SubEnd Class With this added, we can go examine the Reflector disassembly again, and this time we see something very different.  Now we see the call to BeforeTextChange but still no AfterTextChange because it still has no implementation.Now, some important notes about this feature.  Partial Methods must be Subs and they must be Private.  This is to avoid them being compiled away either changing your interface (private) or breaking other code which depends on its results (hence no functions).Implicitly Typed VariablesImplicitly typed variables are not variants, this is very important so I'll repeat myself, Implicitly typed variables are not variants.  These are strongly typed variables which you simply forgo the need to type (as in press keys) the type (as in the class name).The restrictions?  You must initialize the object on the same line it is declared, so that the compiler can infer the type.  Here is an example:Dim myString = "This is a string, I swear"Now myString is a System.String, not a System.Object or anything else.  Object InitializersThis is a minor tweak to something which VB has always been better at than C#.  It makes a more compact version of the With syntax, at the cost of adding curly braces into VB, so you can judge if it's worth it for yourself.Sub Main()Dim ds = New SqlClient.SqlConnection() _ With {.ConnectionString = "Blah"}End SubFor C# this feature is a god send, but C# didn't always have With, so it's your call if this is truly a great feature.Anonymous TypesNow, the addition of With as part of an object initializer is a little ho-hum, but this is not.  Enter Anonymous Types, a strongly typed object where the type is not explicitly declared, but rather implicitly declared.Sub Main()Dim ds = New With {.FirstName = "Tim", _ .LastName = "Rayburn"}End Sub Ok, have I blown your mind yet? No? Well, then try this in for size... On the right is the Intellisense you receive when you type "ds." with this variable in scope.  The compiler has converted out simple syntax above into a full type with two properties : FirstName and LastName.  Pretty darned sexy if you ask me.Restrictions?  Of course there are restrictions.  These can only be used as private or local variables.  If any other type will ever see this object them you have to convert this to a full class.  The VB compiler will let you make these public, but it emits the type as System.Object and you loose intellisense.Embedded XmlThis is a feature that C# 3.0 does not have, it is solely the province of Visual Basic and I must admit, it kind of rocks.  But it will also break your head the first time you read it:Sub CreateCityXml(ByVal name As String, ByVal lat As Double, ByVal lon As Double)Dim cityXml As XElement = _<City><Name><%= name %></Name><Latitude><%= lat %></Latitude><Longitude><%= lon %></Longitude></City> cityXml.<City>.<Longitude>.Value = "XXX"End SubThis feature has to do with LINQ to XML, the basic object of which is the XElement class we are declaring above.  You can with this embed XML directly in your VB code.  Notice there are no line continuation characters after the root node opens, this is because it is assumed that the declare will end when the root node is closed.  Also note the use of the <% and %> like ASP and ASP.NET use to embed code into the XML.  This simple example is simply outputting variables, but there is no reason why this couldn't just as easily have contained a For loop or some other more complex code.The final line before the end of the sub shows how you can also use the XML node syntax as if they were an object model.  Now this does not include Intellisense support for the .<tag> names, but it is still pretty slick.Lambda ExpressionsI know that Visual Basic has a tradition of being a less terse, more verbose language, but I personally feel that VB got the short end of the stick on Lambda Expression syntax.  A Lambda expression is supposed to be a terse syntax for anonymous delegates which also happens to be able to be explored via code if you're using Expression Trees (which we will not discuss here).  For instance, let's assume that you wanted to select items from an List(of Integer) where the value was greater than 50.  You could write code like this:Function GreaterThan50(ByVal inputList As List(Of Integer)) As List(Of Integer)Return inputList.Where(Function(i) i > 50)End FunctionThis is much more verbose than the C# syntax for that Lambda Expression "i => i > 50" but I will grant you it is more readable so hopefully people who prefer VB will prefer the VB syntax.Extension MethodsThe best feature of the .NET Framework 3.5, hands down, is extension methods.  If anyone has sold you on LINQ as the best feature, laugh at them and remind them that LINQ is entirely based on extension methods.What are they?  Simple : The ability to add a new method to an existing type which is only visible to those who implement your extension library.Restrictions? Some.  The biggest is that you do not get access to anything you wouldn't have had access to already.  So creating an extension method is not going to allow you to get access to private or internal types for a class.Benefits? Huge!  As cool as being able to add new methods to classes is, you'll please note I said you could extend types!  This means you can create an Interface and then provide implementation for that interface via extension methods.  In fact, that's how LINQ is done in great part.  The .NET Framework now contains extension methods such as "Where" and "First" and "GroupBy" for the IEnumerable interface.  As such any IEnumerable can use these, without changing the interface at all.Very important note to those who try to stay fluent in both languages, the VB syntax for extension methods is very different than the C# syntax, you'll want to pay very close attention to this.Here are two examples, one extends a class, the other an interface:<Extension()> _Function ToStringNullSafe(ByVal inObj As Object) As StringIf inObj Is Nothing ThenReturn String.EmptyElseReturn inObj.ToString()End IfEnd Function <Extension()> _Sub Dispose(ByVal inObj As IDisposable)If inObj IsNot Nothing TheninObj.Dispose()End IfEnd SubThe first of these extension methods is something every UI developer has wished for, a ToString function which does not blow up just because the variable is Nothing.The second is an ingenious (if I say so myself) and beautiful hack of the IDisposable interface.  Most, but importantly not all, objects which implement IDisposable implement a public Dispose method.  Some however do not, even though they implement it explicitly.  This method will add a public Dispose method to any object which implements IDisposable.What if they already have one you ask?  The actual method on an object always wins out, and if there is a danger to extension methods, that is it.  Should the person who controls that type add a method which has the same name as your extension method, your extension method becomes uncallable.  A minimal risk for the incredible power of being able to provide implementation to interfaces.

Ruby vs. C# Smackdown

I recently attended a meeting of the Dallas C# SIG, a group which I hadn't attended in quite some time, because they had Adam Keys come in to talk about Ruby.  I don't live under a rock, so I've heard the buzz about Ruby but I hadn't spent much time looking into it because it wasn't immensely relevant to my day to day.  That said, this was a great chance to learn so I checked out the meeting and I must admit, I was impressed.  I'm hardly a convert but I can understand Adam's point that Ruby "feels" more enjoyable to write for him. While most things Ruby can do I think C# 3.0 has well in hand, there still some things C# can't do yet.  The dynamic augmentation of an instance, not a type, is intriguing to me and certainly powerful.   One feature that I thought was interesting, and immediately doable in C# 3.0 was the way Ruby can handle loops.  For instance take this Ruby code (syntax errors possible, this is not checked) : 50.Times doPuts "We Built This City ..."Puts "We Built This City ..."Puts "On Rock And Roll"endI like this much better than the standard C# syntax of a For loop because it focuses on what is important.  Its terse yet clear, and I wanted in C# 3.0 right now, so here it is:public static class LoopingExtensions{public static void Times(this int upperBound, Action<int> action){for (int index = 0; index < upperBound; index++)action.Invoke(index);}}This results in a very nice piece of C# code, equivalent to our Ruby example above:50.Times(i => {Console.WriteLine("We Built This City...");Console.WriteLine("We Built This City...");Console.WriteLine("On Rock And Roll");}Simply enough to implement, and a great example of using Lambda expressions and extension methods to improve the readability of your code.

Looking for my next project...

I've recently completed work on a project, and have begun the search for my next project.  If you are in the greater Dallas/Fort Worth area, or don't mind remote workers, and have need of my expertise in BizTalk, C#, WCF, solutions architecture or anything else then please feel free to drop me a line at Tim@TimRayburn.net.