Monthly Archives: June 2004

Visual Basic Power Pack released!

I can’t believe I’m the first person to blog about this (maybe my aggregator’s stuck?), but the new Visual Basic Power Pack has been released on GDN. Here’s a description:

The Visual Basic Power Pack consists of seven custom controls written in Visual Basic .NET 2003. The controls provide enhanced user interface elements and enable you to create more interesting and more colorful client based applications.

The Power Pack controls consist of:

·         BlendPanel. This provides a background for a form where the color fades from one shade to another.

·         UtilityToolbar. This is a toolbar whose look and feel is similar to the Internet Explorer toolbar.

·         ImageButton. This is a button that displays a graphic over a transparent background.

·         NotificationWindow. This displays text and graphics in a pop-up window (commonly known as “toast”).

·         TaskPane. This is a container that provides collapsible frames for displaying additional information on a form.

·         FolderViewer. This displays directories in a hierarchical format.

·         FileViewer. This displays a list of the files in a specified directory.

They’re being released as a sample, so full source code (in VB, of course!) is available. Have fun!

For Each and Option Strict

Duncan pointed me to a thread on GotDotNet that asked a frequently asked question: why doesn’t For Each require a cast when Option Strict is on? For example, the following code is entirely legal:

Option Strict On

Sub Foo(ByVal array() As Long)
    For Each i As Integer In array
        …
    Next i
End Sub

As For Each iterates through the array, each element of the array is automatically cast from Long down to Integer without comment, even though Option Strict usually requires an explicit cast. Why is that? Mostly for developer convenience with dealing with collections such as Collection or Arraylist. In those cases, the element type of the collection is always Object. If we required a cast to iterate through a collection of Object values, where would you put the cast? There’s no place to actually do the cast in the For Each statement, so you’d be stuck having to have your iterator variable be typed as Object and then doing the cast yourself into anoher variable:

Option Strict On

Sub Foo(ByVal array As ArrayList)
    For Each o As Object In array
        Dim i As Integer = CInt(o)
        …
    Next i
End Sub

Since ArrayList/Collection object tend to have the same type in them and people iterate through them a lot, we decided that it made more sense to bend the rules in this case and do the cast automatically for you. (You can thank us later.) As an interesting side-note, C# does exactly the same thing in their foreach statement.

Conversion operators in VB

In my entry on “native” languages on the CLR, I made a blanket statement that the intrinsic VB conversion operators would be faster than the conversion functions in the Convert class because they compile down to IL rather than function calls. In my quest to emphasize my point, however, I made a serious misstatement which was not intentional but should be corrected. Not all intrisic operators compile down to simple IL instructions, although most do so. And the ones that don’t are worth discussing. So let me spend a moment talking about conversions.

The intrinsic conversion operators (CObj, CByte, CShort, CInt, CLng, CDec, CSng, CDbl, CDate, CStr, CChar, CType, DirectCast) generally fall into several broad categories of implementation:

  1. Conversions that are pure IL statements. The best example here is the conversion from Integer to Long or Long to Integer. This compiles directly down to a conv.i8 or conv.i4.ovf instruction, respectively. You really, really, really don’t want to be calling functions to do this kind of conversion unless you’ve got a lot of faith in inliners, which I generally don’t.
  2. Conversions that are mostly pure IL statements. The best example here is the conversion from Double to Integer. This compiles down to a call to Math.Round and then a conv.i4.ovf instruction. The purpose of the extra call is to implement banker’s rounding, which the CLR doesn’t natively support. (In banker’s rounding, a decimal number equidistant between two whole numbers is rounded to the nearest even number. So 3.5 rounds to 4, but 2.5 rounds to 2.) In this case, calling Convert.ToInt32(Double) is not the same as CInt(Double), and you have to choose which semantic you desire.
  3. Conversions that are calls to the Convert class. The Decimal type is not natively supported by the CLR. As such, conversions to and from Decimal (with the exceptions listed below) turn into calls to Convert.ToDecimal() or the appropriate helper. There’s no point in us reimplementing the conversion since it’s the same for both the CLR and VB. In this case, calling Convert.ToDecimal(Integer) is exactly the same as CDec(Integer).
  4. Conversions that call VB specific helpers. There are only two cases that fall into this category: conversions to and from String, and conversions from Object.
    • Conversions to and from String call VB specific helpers because VB does a variety of extra things for you. For example, when converting String to Integer, we’ll parse decimal numbers and do the appropriate rounding. So while Convert.ToInt32(“10.5“) will barf with an exception, CInt(“10.5“) will work just fine. And this is just one example of the nice stuff that we’ll do for you. As always, though, extra functionality can equal extra cost. So if you just want the very basic functionality that Convert.ToInt32() calls (or you prefer calling two functions), you might get slightly better performance by calling it instead of using CInt on a String.
    • Conversions from Object call VB specific helpers because VB needs to be able to implement VB specific semantics (such as the String conversions and banker’s rounding) when converting values from one type to another. For example, Convert.ToInt32(CObj(“10.5“)) still throws an exception, while CInt(CObj(“10.5“)) won’t.

One interesting thing to note is that if you really want only the CLR conversions and nothing else, the DirectCast operator will turn off most of the VB-specific conversion features (I believe we still do banker’s rounding, though). Then you can call the Convert class methods when you run into conversions that DirectCast doesn’t support. I still think that this is an extreme way to go about things, but I know some people are just that way. Me, I use the regular VB operators and then look out for performance sensitive areas where I might need something different.

Let us now mourn the passing of ‘Firefly’…

Six months ago, my trusty TiVo starting developing a pretty bad stutter that signaled the death of it’s original hard drive. Filled with unearned confidence, I decided that instead of buying a new one, I’d just upgrade it with new, bigger hard drives. (We can rebuild him, stronger, faster than before…) So after buying two 160 gig hard drives and nearly killing myself prying the damn cover open (it was the first time I’ve ever seen an unshielded power supply), we had all the recording capacity we needed. As such, we no longer felt motivated to keep up with TV, knowing that the shows would all be there for us during the summer drought.

Then, a month or so ago, we came home from a long weekend to find the TiVo totally hung. Tried a reboot, hung. Finally determined that one of the new hard drives had gone kablooey, so sent it off to Maxtor for a replacement and restored the backup image that I made six months ago to the remaining good hard drive. As a result – all those saved shows were gone. What in the world are we going to watch instead?

Which is all a loooong way of getting to the fact that we’re finally getting around to watching the Firefly DVD set that I got for Christmas. Before I go any further – if you haven’t seen Firefly and/or haven’t bought the DVD, go back and click that link and buy it. Done it? OK, now we can continue. I’ll have to admit that I’ve never gotten into Buffy the Vampire Slayer or Angel, so when I heard that Joss Whedon was doing a wild-west sci-fi show, I thought “probably won’t be any good, but, hell, it can’t be any worse than the crap Star Trek is pumping out these days.” So I set TiVo to record it and figured I’d see what happened.

And you know what? I’d have to say that Firefly is the finest damn science fiction show that I’ve seen in a very long time, and what Fox did to it was just a (pardon my French) fucking travesty. It wasn’t a revelatory show in the sense that it blazed radical new ground in science fiction. Instead, it was just a really well put together show that combined a good cast with a lot of really fine, well thought out writing. In most ways, the science fiction aspect of the show is incidental to the emphasis on the human aspect, something that has been totally excised from the increasingly robotic (and paint-by-numbers) Star Trek franchise and it was just so… so… nice to actually watch a show where the characters actually had some depth and acted like real human beings. And I would have to say that the last two minutes of the ‘Ariel’ episode genuinely put me on the edge of my seat, something that hasn’t happened in a long time.

So now Andrea and I are working our way though the scant fourteen episodes that Fox made before pulling the plug. If it’s an indication, Andrea is about non-geeky as you can get (i.e. could not care less about Star Wars, Star Trek, etc.) but she’s loving the show too. It’s just sad that now we’ll probably never really know where it all was headed. At least there are the three unaired episodes that we’re going to reach pretty soon, so I’ll get a little something extra before having to say goodbye again.

Some shows pass too soon, some shows last well past their prime, I guess it’s the way of the world.

The Truth about Nullable Types and VB…

There’s been a little confusion about how VB’s going to handle nullable types in VB 2005, so let me try and amplify a little bit on the entry on the VB team blog.

What are nullable types?

One of the primary differences between value types such as Integer or structures and reference types such as Form or String is that reference types support a null value. That is to say, a reference type variable can contain the value Nothing, which means that the variable doesn’t actually refer to a value. In contrast, a value type variable always contains a value. An Integer variable always contains a number, even if that number is zero. If you assign the value Nothing to a value type variable, the value type variable just gets assigned its default value (in the case of Integer, that default value is zero). There is no way in the current CLR to look at an Integer variable and determine whether it has never been assigned a value – the fact that it contains zero doesn’t necessarily mean that it hasn’t been assigned a value.

Unfortunately, there are situations where it would be nice for value types to have an actual null state. The most common example is in a type that represents information from a database. Many databases allow columns of any type to contain a null value that means “you didn’t assign a value to this column.” For example, an Employee database might assign null to the Salary column of retired workers, meaning that they no longer have a salary (instead of assigning some magic value like zero to their salary, which might be accidentally confused to mean that they are still working for no money). The fact that the CLR doesn’t support null values for value types can be somewhat painful in this situation and is the reason that we have the System.Data.SqlTypes namespace. But those types do a lot of extra SQL-type stuff. Wouldn’t it be nice to have this for all value types?

The answer to this is yes, and the generics support added in VS 2005 allows us to do it. In VS 2005, we’re introducing a new generic type called Nullable(Of T) that adds nullability to any value type. How it does this is beyond the scope of this entry and is left as an exercise for the reader. But, suffice it to say, it works just fine. Here’s an example:

Sub PrintValue(ByVal i As Nullable(Of Integer))
    If i.HasValue Then
        Console.WriteLine(CInt(i))
    Else
        Console.WriteLine(“Null value!“)
    End If
End Sub

What is C# doing?

From this base level of functionality, C# is taking nullable type support a bit further in VC# 2005. The primary features they’re implementing are:

  • A new type modifier ? that means “nullable.“ So instead of writing “Nullable<int> i;“ in C#, you can write “int? i;“.
  • A “coalesce“ operator ?? that is a quick way of converting a nullable type to a non-nullable type with a default value. So “int x; int? y; x = y ?? 0“ will assign the value of y to x if it is not null, and will assign the value 0 to x otherwise.
  • Lifted conversions. If a type T has a conversion to type U, then the type T? will have a convertion to type U?. This means you can convert an int? to a long? without having to do explicit null checks.
  • Lifted operators. If a type T supports an operator X, then the type T? supports the same operator. This means that you can add two int? values and get an int? value in return without having to do null checks.

Beyond the question of convenience, the last point means that nullable types in C# will support null propagation semantics. If you add two int? values and one of them happens to be null, then the result of the addition is going to be null. The one place where they break this is for comparison operators – unlike a language like SQL, comparing two nullable types is always going to result in a bool value, not a bool? value. I understand why they’re doing this, but it is an unfortunate thing to have to do.

What is VB doing?

Very unfortunately, nothing will be done in VB 2005 beyond what’s already supported by the Nullable type. We would very much like to support features along the lines of what C# is doing (although I don’t think you’ll ever be writing “Dim x As Integer?”), but nullable types were introduced into the BCL too late in the product cycle for us to be able to add extra features this time around. It’s very disappointing, to say the least, but we do look forward to adding more support in the future. (One interesting point is that it is likely that VB will be able to preserve null propagation when lifting comparison operators because we have two comparison operators. Score another point for Is vs. =.)

This isn’t to say that Nullable types won’t be very useful in VB – just that some extra niceties you’ll get in C# will be, um, temporarily unavailable. May we suggest while you’re waiting that you enjoy the other fine features of our language?

WWMD? What Would Microsoft Do?

In the continuing discussion on language choice, Sriram has a comment:

I’m a big VB guy myself. But it is easy to see why this myth is perpetuated. Check out Microsoft itself. Of all the teams using managed code, how many teams are using VB.NET for development? […] If you want more people to take Vb seriously, Microsoft has to show that they trust it enough to use with their own products

I’ve heard this one a lot, too, so I think it’s worth taking a moment to address it as well. Or, really, expand on the comments that yag made.

The interesting part about all this is that, in many ways, nothing has changed with .NET. If you cast your mind back to the antediluvian time before .NET came onto the scene (i.e. VB1 – VB6), you’ll remember that all major products written by Microsoft were not written in VB, they were written in C or C++. Now, that was more of a matter of necessity than choice in most cases because VB had limitations that prevented it from being used to write, say, Word or Windows. But the fact of the matter was that even though Microsoft wrote no product in VB, VB was no less important or significant to the company. Similarly, to the degree that Microsoft groups do or don’t use VB on .NET has nothing to do with how important or significant VB is to the company.

When people ask me “should I use VB or C#?”, the first question I ask them is “What are you programming in right now?” If the answer is VB, then I tell them to use VB .NET as it seems to me to be a no-brainer. If the answer is C or C++ or Java, however, I start plumbing deeper because in many cases the right answer is going to be to start by using C# because that’s going to give them a much more familiar experience. (In other cases, I recommend C++ and I think the work the C++ group is doing for VS 2005 is just great.) By moving to C# from those other languages, they retain the familiarity with the syntax, the semantics and the IDE – C# is really optimized in many, many ways for the migrating C-derived language programmer. Given that, I am untroubled by the fact that much of the base class libraries, for example, are written in C#. Most of the programmers who worked on those libraries were moving from – yes, you guessed it – C++ or Java, so by my own logic, C# was a logical choice for them.

However, that doesn’t mean that Microsoft is just going to be a C# shop and that’s it. The wonderful and important thing about .NET is that it provides a very level playing field for languages that support it. Whereas I wouldn’t have suggested writing Word in VB prior to .NET, now there isn’t any great reason why new applications need to be written C# rather than VB. So we’re definitely starting to evangelize VB within Microsoft, starting with our own team. In VB 2002, we wrote our runtime (Microsoft.VisualBasic.DLL) in VB, which was a first for us. In VB 2005, more libraries and several of the pieces of managed code in the IDE are going to be written in VB. And beyond VB 2005, we’re pushing for even more managed code to be written in VB.

Now, is Longhorn going to suddenly switch all their developers over to VB en masse? I’m not holding my breath. But it’s actually an exciting sea change to be able to make inroads into a world that was, up until .NET, exclusively a C-derived language domain.

(Sriram raised one other point that got elided above – Microsoft has had an issue in the past with demos and sample code being too heavily weighted towards C#. This issue has been taken very seriously at high levels and we’ve been working to balance this out, because it has both a symbolic and practical value. If there are areas where you feel we’re too unbalanced, let us know! I can tell we’re doing better because we’re starting to hear complaints from people that “too many of the demos/samples were in VB!” If everyone’s unhappy then we’re probably starting to strike a more reasonable balance…)