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 NewFeatures
    Partial PrivateSub BeforeTextChange(ByVal oldText AsString, ByVal newText AsString)

              End

              Sub

            

    Partial PrivateSub AfterTextChange(ByVal oldText AsString, ByVal newText AsString)

              End

              Sub

            


              Private _text AsString

              Public

              Property Text() AsString

              Get

            

              Return _text

              End

              Get

            

              Set(ByVal value AsString)
            BeforeTextChange(_text, value)
            _text = value
            AfterTextChange(_text, value)

              End

              Set

            

              End

              Property

            

              End

              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 NewFeatures

              Private

              Sub BeforeTextChange(ByVal oldText AsString, ByVal newText AsString)
        newText += oldText

              End

              Sub

            

              End 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 Variables

Implicitly 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 Initializers

This 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

              Sub

            

For 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 Types

Now, 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

= NewWith {.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 Xml

This 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 AsString, ByVal lat AsDouble, ByVal lon AsDouble)

              Dim cityXml As XElement

= _
    <City>
        <Name><%= name %></Name>
        <Latitude><%= lat %></Latitude>
        <Longitude><%= lon %></Longitude>
    </City>

    cityXml.<City>.<Longitude>.Value = "XXX"

              End

              Sub

            

This 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 Expressions

I 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

              Function

            

This 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 Methods

The 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 AsObject) AsString

              If inObj IsNothingThen

              Return

              String.Empty

              Else

            

              Return inObj.ToString()

              End

              If

            

              End

              Function

            

<Extension()> _

              Sub Dispose(ByVal inObj As IDisposable)

              If inObj

IsNot NothingThen
        inObj.Dispose()

              End

              If

            

              End Sub

The 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.