Category Archives: Visual Basic

How do you do two mutually exclusive things at the same time?

As an example of how VB .NET threw its lot in with the MSDN camp instead of the Raymond Chen camp, Joel points to the example of the disappearance of Set and parameterless default properties. (I should add that Joel slightly misspoke again – VB still has default properties; now, though, they can’t be parameterless.) This is an interesting design point to pick because it was one of those that unambiguously showed the dilemma that we faced when moving to .NET. Namely, how do you do two mutually exclusive things at the same time?

You see, when we started out on the grand .NET experiment, lo those many years ago, we were all Raymond Chen-ites, every one of us. We were going to port VB to this new .NET platform and, by golly, it was going to be 100% compatible with the previous version. We had all kinds of assurances from the CLR team that they were going to support whatever we needed to make us compatible. We had all kinds of directives from management that compatibility was paramount. So we set off busily building a product that would allow migrating VB6 code unchanged to this new platform and would make VB .NET be a no-brainer upgrade for our millions of users.

So, what happened? Among other things, reality asserted itself.

Let’s use Joel’s example, because it’s an excellent one. One of the cornerstones of .NET was that it was a multi-language platform. No longer would one language be crippled in favor of another – no! We were all going to be on a level playing field. Only… well… there’s this little problem with assignment operators. Because, you know, VB has these two types of assignment: value (Let) assignment and reference (Set) assignment. And the C-style languages (C++, Java, C#) have only one type of assignment that changes meaning depending on the type of value you’re assigning. OK. No big deal, right? Each language can keep its own way of dealing with assignment, right?

Yeah, but then there’s properties. A key feature of properties is that they allow you to define what happens when you assign to the property. Hmmm. Assign. As in the assignment operator. As in “two types of assignment” vs. “one type of assignment.” But we’re still cool, right? Because the CLR allows you to define multiple “set” accessors for properties. Yes, that’s it, VB properties will allow users to define both a Let and a Set property accessor and the C-style languages will allow users to define only a Set property accesor. And everybody will be happy, right?

Until they try and work together, that is. You see, the flaw in this little argument is: what about the class libraries? Yeah, class libraries. Little things like, oh, WinForms and the Base Class Libraries. Because, you see, those libraries were supposed to be used by both VB and the C-style languages. And there was just no way to finesse the issue that the two language camps had two approaches to assignment when trying to write properties that would work with both languages equally well. Believe me, we banged our head against the wall for a long time trying to invent some scheme that didn’t require one language or the other to contort itself. We thought about ways to make properties with just a Set to map correctly to a Let/Set. We thought about ways that properties with a Let/Set could map correctly to just a Set. In the end, though, we came to the conclusion that there was no good answer. Either we had to foist what looked like completely arbitrary requirements on programmers working in the C-style languages (i.e. surface the “two types of assignment” in C++/C#), or we had to deliver a seriously sub-par experience for developers working in VB (i.e. surface the “one type of assignement” in VB). Or we could take a third way – drop Let/Set assignment, drop parameterless default properties, break existing code that used them, and adopt a unified type of assignment.

To be clear, this is not “the reason” why VB .NET is not 100% compatible with VB6. This is just “a reason” that is representative of the sea-change that existed when moving from the Win32/COM platform to the .NET platform. But it is illustrative…

(As a postscript, I’ll add that parameterless default properties were always a bit weird because it appears there were never any clear rules about how they worked. If I remember correctly, not even the developer who owned the compiler’s semantic analyzer at the time could explain what was supposed to happen in some fairly straightforward cases. The spec was the code – as long as test cases from previous versions worked, the code was “right.” Ug.)

Save Ferris! I mean, VB6!

A few days ago Scoble emailed me with the heads up on his post talking about the MVP revolt spurred on, in part, by the fact that VB 6.0 mainstream support is ending this month. Then life intervened and I’m just now getting some time to get back to the whole brouhaha. In the meantime, this has roiled through at least a few corners of the blogsphere. I’d throw in a couple of gratuituous links, but if you read any number of .NET or VB blogs, you’re going to have seen them. Well, OK, two entries that stand out in my mind were those of Dan Appleman and Scott Swigart. There were plenty others that I although thought were good, but one man can only link so much. The petition itself can be found here.

I should start off with the statement that I have a great amount of sympathy for people who have not yet made the move off of VB6 and who would very much like to see support extended even further than it already has. I know that support can be a real issue and is something that people worry about. Beyond that, though, I can’t really say anything because I’m not even remotely involved or included in decisions about things like product support. I, along with the rest of you, will be interested to see what kind of response the outcry elicits.

As for the petition itself, it asks for two main things: 1. That we develop new versions of “unmanaged VB”, and 2. That we integrate those new versions of “unmanaged VB” into the Visual Studio shell.

To start with the second point first, to those who think we should integrate VB6 into the current Visual Studio shell, I can only offer the perspective of a developer who’s worked in both codebases: best of luck. In VB6, all of the pieces of the puzzle (compiler, debugger, forms package, runtime, etc.) were designed to work solely with each other and were tightly bound together. In Visual Studio, all of the pieces of the puzzle were designed to work with mutiple clients and were loosely bound together. Thus, the architectures are totally different and, in many ways, incompatible. Heck, we spent four years getting VB .NET integrated into the Visual Studio shell and we were writing it from scratch (and therefore could design a compatible architecture)! Trying to extract some of the pieces of VB6 and fit them into an architecture that was not designed to couple with them as tightly as their previous home would be a huge undertaking.

And when I talk about a “huge undertaking,” I’m not talking huge in terms of fungible stuff like money or people. I’m talking huge in terms of non-fungible stuff like time. No matter how much money or how many people we threw at the problem, it would still be a significant amount of time before anything could be produced. I’m talking, like, years. So, now we’re talking about having something in, what, 2007? 2008? At best? Ten years after the previous version of “unmanaged VB” shipped? I’m not really sure how that’s going to make much of a difference to the issues that people are confronting today.

Now, obviously, we could still satisfy the first request by shipping a new version of VB6 that wasn’t integrated into the Visual Studio shell, and that would take a lot less time. At this point, though, I don’t believe that even that would really buy people that much. Leaving aside the question of the desirability of a separate-but-sort-of-equal development envrionment, Microsoft has stated very clearly (pace Richard) that managed code is the direction that our company’s components and APIs are headed. As such, fostering new development (as opposed to extending support for existing development) in “unmanaged VB” doesn’t just postpone the inevitable, it makes it worse. It encourages people to keep writing a lot more code that, somewhere down the road, they’re going to have to port to .NET. It’s alleviating pain in the short term only to cause greater pain the long term, something that I don’t think it would be responsible for us to do. (One part of the petition that did mystify me a bit was the request to “Ease […] migration of unmanaged VB/VBA code to VB.NET.” Does anyone think that we haven’t been working on that?)

So, while I can be sympathetic to where the petitioners are coming from, I can’t ultimately support their stated goals. Obviously, we continue to have work around helping people make the transition from COM to .NET at their own pace and helping them be clear on the advantages of doing so. VB 2005 is going to help a lot here, I think, and we continue to work on even more things for the road beyond. In the end, I think that’s the best thing we can do.

When a step forward looks like a step backwards…

One of the things that would be amusing if it wasn’t so annoying is the way that a step forward can be perceived by people as a step backwards. Case-in-point: the commonly heard refrain that C# is the “official” language of .NET (and Microsoft) because so much of the frameworks are written in C#. Scott has a pretty good set of arguments against this canard framed in the context of the present day, but the thing that I find really ironic is how all this hand wringing is so woefully ignorant of history and how it is backhanded evidence of the essential correctness of the strategy of moving VB to .NET.

To wit: can anyone tell me, for the ten years (give or take) between the introduction of VB 1.0 and the introduction of VB .NET 7.0, how much of the Win32 APIs or the COM APIs were written in VB?

Of course the answer is: none, to my knowledge. In fact, the VB team itself did not use VB in any meaningful way in its own product. The VB runtime functions were all written in C/C++. The VB forms package was written in C/C++. All of the VB controls were written in C/C++. Beyond the VB team, every major Microsoft product and operating system was written using C/C++. Every. Single. One.

Now, during that time was there massive hand wringing about how “C++ is the official language of Microsoft” and how “I’m going to use C++ over VB because that’s what Microsoft uses”? Of course not. Why not? Because VB and C++ lived on two almost completely different planets. C++’s great advantage was that it had full and easy access to the entire power of the platform; it’s greatest disadvantage was that you had to do every damn thing for yourself. VB’s great advantage was that it took care of a lot of the nitty-gritty for you and make programming easy; it’s greatest disadvantage was that it didn’t have full and easy access to the entire power of the platform. (Instead, you often had to turn to advanced books or gurus to accomplish what should have been simple tasks.)

The reason why there is so much angst about this question now is because, for the first time, we’ve accomplished a relatively level playing field on .NET. VB is no longer limited in what it can do with the platform – if you need to customize what you’re doing with WinForms, for example, you have pretty much an unlimited ability to do so. And C# and C++ (using their CLI binding) now can take advantage of all the cool automatic features that VB users have been taking advantage of for decades.

So the bottom line is: as far as an “official” language goes, things are the same as they ever were. Actually, that’s not true: with the introduction of VB .NET, for the first time Visual Basic is being used in a meaningful way inside the company. Several of the libraries in the CLR 1.x were written in VB, and there will be even more VB code in the CLR 2.0. So, ironically, VB is actually much more of an official language at Microsoft than it has ever been, yet the external perception is just the opposite.

Which is why this particular line of argument grates on my nerves like nails on a chalk board. My suspicion is, though, that this erroneous line of thought has mostly been fueled by legitimate problems in the past with the messaging around .NET. What matters to people is not so much what the frameworks are written in, but instead what language we use to talk to the public with. All the hoopla around the new C# language combined with the natural affinity that many MSFT people feel for C-style languages (c.f. the last few paragraphs) meant that, for a while, things like talks, samples, and all manner of other code displayed publicly skewed heavily in the direction of C#. This was a mistake, and one that we’ve been working hard to correct – we’ve been very active in educating people internally as to how their language choice for example code can be perceived outside of the company. We’ve made a lot of progress, although there’s always more work to be done.

As for the whole “what the frameworks are written” in thing goes, maybe we should just decompile the frameworks using Reflector, recompile it using VB, and provide a “VB CLR”… (Note to the humor impaired: this is a joke.) Except, of course, for the non-trivial chunks of the frameworks that are written in C++…

VB: Wired or Tired?

I don’t usually just link to other entries, but sometimes people just say thing that I’ve been meaning to say but just never found the right words for. Scott’s entry on the joys of VB, .NET style, express pretty well the answer to the question of “why VB in .NET?” And I particularly liked Paul Kimmel’s article “Has Visual Basic Lost Its Way?” As I’ve said many times, so much of the past two releases (and the upcoming one) has been just about getting VB onto .NET, which has been a huge endeavor. Not to mention being, for the most part, almost purely reactive – a lot of our feature plans have been driven by the features that show up in the CLR. Part of the angst about VB is that people tend to look at that and extrapolate more of the same: more reactivity. But the point is that with the release of Whidbey, VB will finally be fully caught up in terms of supporting .NET. Which means that we can now look ahead to ways in which we can make “the next big thing” happen on .NET. Stay tuned…

Singletons and Default Instances

In my previous entry, I described what default instances are but left open the question of why we’re re-introducing them into the language. So let me spend a moment discussing that.

A default instance is, more or less, an instance of the design pattern called a singleton. A singleton is a type that only ever has one instance (hence the “single” part of “singleton”). Forms are often an excellent example of singletons because there is usually only ever going to be one instance of the form (with the exception of less common situations like MDI windows). For example, you only need one instance of the File Open dialog because there will only ever be one File Open dialog on the screen at a time. Rather than having to allocate an instance of the dialog every time you need one, or holding on to the same instance in some random place in your application, a singleton has a central location where the single instance is stored.

In most languages, you have to manage singleton objects yourself. This is usually accomplished by sealing the type (i.e. making it NotInheritable), making it uninstantiable (i.e. making its constructor Private) and exposing a shared property called something like DefaultInstance that returns, well, the default instance. If only the language would do that management for you automatically, how nice would that be? If only…

So now we arrive at the rationale for default instances, aka singletons: we think it’s a more natural way of working with objects that always or almost always have a single instance.

I’ve been using forms as an example up until this point, but let me expand the scope a little bit to illustrate my point. Web services are another example of a natural singleton object. When an application interfaces with a remote web service, there is typically only ever going to be one web service proxy instantiated. In VB 2002 and 2003, it is necessary to create a new instance of a web service proxy and then hold on to that instance for as long as you wish to use the service. If you wanted to share the service across multiple objects, you had to make sure to store the instance somewhere where everyone who needed it could get at it. And, truth be told, all of this management code had nothing to do with your program logic. It was just boilerplate that everyone has to write again and again and again.

In constrast, VB 2005 adds a default instance to web services. When you add a reference to a web service Bob, you automatically get a default instance at My.WebServices.Bob. No need to remember to create an instance of the proxy. No need to sock that proxy away somewhere so that everyone can get at it. It’s just… there. Without you having to do anything to make it so.

This seems like a good thing, but don’t just take my word for it. After all, you can go read about how to implement the singleton pattern in C# and how to implement singleton forms in C#. And then you can come back to VB and find that we already did it for you… (I should add that Justin’s singleton form entry touches on a specific problem having to do with the design of WinForms that I’ll address in the next entry.)

Well, that’s about it for the moment but we’re not done yet… I still need to cover the problems and issues that have been raised around default instances, which I will cover next. That entry, tentatively titled “Default Instances Considered Harmful” is coming soon.

]]>

Default Instances

Fresh off of writer’s block, I thought I’d dive straight back into the sea of controversy and talk about a feature called “default instances.” Default instances are a “new” feature in VB 2005 that is really the return of a very old feature, one that’s been around for a long time. Now, the return of default instances has stirred some very passionate debate, but what I’m going to do is address this question in three separate entries. In this entry, I’m going to describe what default instances are at a technical level. In my next entry, I’m going to talk about what I see as the positive case for default instances. Then, in the final entry, I will talk about some limitations of default instances and address the controversy about their reintroduction more directly. You can choose whether or not you want to wait for the last entry before you start throwing brickbats…

So, what are default instances? Well, they’re exactly what their name suggests: a way to provide a default instance of a class that you can use without having to New the class. If you’ve used versions of VB prior to VB 2002 (i.e. pre-.NET), you’ll probably have come across the most common default instance, the form default instance. For example, in VB 6.0, if you created a form named Test, you could say in code:

Test.Show()

And voila! an instance of the form would just magically appear. What was going on behind the scenes was a bit of magic. When you referred to “Test,” the VB runtime would go check and see if it already had a default instance of Test lying around. If it did, then it would hand back that default instance when you called Show(). If there wasn’t a default instance lying around, the runtime would create a new instance of Test and use that as the default instance going forward.

Default instances disappeared in VB 2002 and VB 2003, but are making a comeback in VB 2005. The high-level “why,” I’ll leave to my second entry, so let’s talk about the “how” for the moment. Hopefully, all of you are familiar with the introduction of the My namespace in VB 2005. (If not, go read this MSDN article and then come back.) One part of the My namespace is the Forms object. If you bring up a VB 2005 project with a Form named Test in it, you’ll notice that the My.Forms object has a property called Test. This property returns a default instance of Test. So you can say, sort of like you did in VB 6.0, “My.Forms.Test.Show()” and voila! up pops a new instance of Test. What happens behind the scenes is that the Test property of My.Forms checks to see if it’s already returned an instance of Test and, if it has, it just returns that instance. If it hasn’t returned an instance yet, it just creates a new instance. Pretty simple.

We also extended default instances to work in exactly the same way that VB 6.0 default instances did. Besides saying My.Forms.Test.Show(), you can also just say Test.Show() and it will also access the default instance. Essentially, Test.Show() is a shortcut to saying My.Forms.Test.Show().

There are, however, a couple of differences between the way default instances are implemented in VB6 and the way they are implemented in VB 2005:

  • In VB6, if you tried to use the Is operator to test the default instance to see if it was Nothing, the expression would always evaluate to False. This is because referring to the default instance caused it to be created if it didn’t exist! In VB 2005, we recognize when you are testing the default instance using the Is (or IsNot) operator and won’t auto-create the instance in that case. So you can see if the default instance exists or not.
  • A common source of default instance errors was using the default instance instead of Me within the default instance’s type. For example, if Form1’s load method has the statement “Form1.BackColor = Color.Red”, this will only change the background color of the deafult instance’s form. If you create a new instance of Form1 that is not the default instance, it’s background color will not be red! To assist users in this case, we give an error when you refer to the default instance inside of the type, telling you to use Me instead.

Well, that’s about it for the technical side of things. Now onto the good, the bad and the ugly…

Feedback request on new warning

We’ve been internally discussing a new warning that we’ve added to VB 2005 and how we should treat it for upgrade, and I’d like to get some feedback from those people who have been using the beta or the community previews. A common error that we see is using a reference variable before it’s been assigned a value. For example:

Dim x As Collection
x.Add(10)

This code will throw an exception because I forgot to create a new collection using New. In VB 2005, this code will produce the following warning:

Variable 'x' is used before it has been assigned a value. A null reference exception could result at runtime.

We determine this warning by doing flow of control analysis on the function and determining that you’re using the variable before you gave it a value. This is all well and good, but the warning isn’t perfect. Just because a variable hasn’t been assigned a value doesn’t necessarily mean that there’s going to be a problem. For example:

Dim x As Collection

If Test() Then
x = New Collection()
End If

If x IsNot Nothing Then
x.Add(10)
End If

The test “x IsNot Nothing” will cause a warning that x might be used before it has been assigned a value. This is sort-of true if you look at the code in a simplistic way, but it’s really not a problem, of course, because we’re just testing against Nothing. An ideal solution, and one that we’re considering beyond VB 2005, is to add a more sophisticated level of analysis to the compiler that would allow more fine-grained analysis of null reference problems that would recognize the above situation as safe. But that’s beyond the scope of this release. For now, the level of analysis that we can do is identify places where you used a reference variable without assigning it a value.

Now, to the question: have people found this warning to be annoying on upgrade? New projects don’t seem to have major issues with this warning because you fix the warnings as you go along, by and large. But upgraded projects can be a different story: depending on the coding style used, a project might have a ton of these warnings show up when you first open it in VB 2005. For example, I recently upgraded the VBParser project and spent a little while fixing up 100 or so of these warnings, all of which were what you might call “false positives” – I was using variables before they had been assigned, but always in a safe and courteous manner.

What have people’s experiences been with this warning on upgrade? Was it annoying? Was it helpful? Would it be desirable to not have the warning turned on by default in upgrade? Just to be clear: we’re not planning on changing anything as it stands right now. But now that the beta’s been out in the wild for a while, we thought it might be a good time to validate our assumptions against some cold, hard customer feedback…

Welcome Slashdot…

So every time someone whose blog I read would get Slashdotted, I would wonder to myself, “I wonder if this will ever happen to me?” And then I would start speculating, “Hmmm… If so, I wonder what kind of thing I’d have to do to get myself Slashdotted…” Well, now I know: have Microsoft submit a patent for the IsNot operator, listing me as the principal inventor. Wonderful. Glad to see it’s over something that I can be really, really proud of…

(It’s not a full Slashdotting I suspect, because the blog is only mentioned in the comments, not the main entry, but even a tertiary flood is interesting…)

Updated: Corrected the misuse of “principle” when I meant “principal.”

]]>