Category Archives: Visual Basic

Late bound overload resolution and structures

I was just reviewing some notes I made about updating the language specification and I came across this little gem: What do you think the following code does?

Option Strict Off
Structure MyStruct
Public MyField As Integer

Public Sub Mutate(ByVal x As Byte)
MyField = x
End Sub

Public Sub Mutate(ByVal x As Short)
MyField = x
End Sub
End Structure

Module Module1

Sub Main()
Dim o As Object = 5S
Dim s As MyStruct

s.MyField = 10
s.Mutate(o)
MsgBox(s.MyField)
End Sub

End Module

Yes, that’s right, it prints 10. Why? Well, it has to do with how we handle overload resolution and loose-typing.

When we were originally coming up with the rules for overload resolution, we noticed a particular problem with loosely-typed code (that is, code that doesn’t explicitly state the types of its variables). Because all the variables in a loosely-typed program are typed as Object, there are a lot of places where the regular overload resolution rules fall down. Take the example above: if you follow the normal rules of overload resolution, the call to s.Mutate is ambiguous. That’s because the argument type is Object and the two parameter types are Byte and Short. Object has narrowing conversions to both Byte and Short, so we can’t actually choose between them.

However, we thought, at run-time all values become strongly typed. So even though the variable may be statically typed as Object at compile-time, if we defered the overload resolution to run-time, we could probably resolve the overloading correctly. (I should point out again that this only applies to loosely-typed programs: in a strongly typed program, you’d just insert a cast to resolve the ambiguity.) So we added a special “loosely typed overload resolution rule” to handle this situation: if overload resolution produces an ambiguous result solely because of narrowing conversions from Object, then we defer the resolution until run-time. Or, in other words, we make the call late bound. This isn’t such a bad thing because if you’re doing loosely-typed programming, by definition you’re going to be doing a lot of late binding anyway.

OK, so all is well and good, no? Well, not exactly. You see, the problem in the above situation is that to make the call to Mutate late-bound, we have to call some helper functions at run-time. And those helper functions take the target of call as a value typed as Object (since you can late-bind against any type). Which means that we have to cast the target of the call to Object. Which means that, since MyStruct is a structure, we have to box the value. Which means that the target of the call is no longer the stack location indicated by s, but instead some heap location where we boxed the value to. Which means that Mutuate changes the heap location instead of the stack location, and so the change is lost when the method returns.

This is an unfortunate subtle interaction between two features. The good news is that you really only will get into trouble when mixing strongly-typed with loosely-typed code. If, in the example above, you’d typed s as Object and assigned it a new instance of MyStruct, everything would have worked as expected because the structure would always have been boxed. On the other hand, if you turn Option Strict On, the above example will give you an error on the overloaded call to Mutate and will require you to resolve the ambiguity with a cast. So the chance of anyone running into this is thankfully remote.

Performance matters!

I was chatting with some of the people on our performance team (i.e. the people who are supposed to make sure VB is as speedy as possible), and they were talking about some plans they were considering to help gather public feedback on problem areas in the product. “What about the MSDN Product Feedback Center?” I asked. “We hadn’t thought of that,” they replied, “perhaps you should blog about it!” So consider it done. I am now officially encouraging everyone to report any major performance problems you’re having with VB using the MSDN Product Feedback Center.

To ensure that your bug gets the amount of attention due it, here are several suggestions:

  • Put the word “Performance:” in the title of the bug.
  • Include the general hardware specifications (CPU speed, memory, etc.) that you’re testing on.
  • Include any changes to the environment that you’ve made (i.e. what tool windows are showing, which profile you are using, etc.).

And, most importantly:

  • Include specific steps that will allow us to easily reproduce the problem.

The last point is important to ensure that we actually can do something in regards to your bug report. Saying “the product is slow,” isn’t going to help us. Saying “when I show the Autos window and then hit the Step Through toolbar button on this code, it takes several seconds.” is more like it. Remember, the more specific you are, the higher chance we’ll be able to fix the problem.

I’m also talking to Robert Green to see if we can’t get a specific “Performance” Problem Type added to the Feedback Center to help categorization. The wheels grind slowly, though, so it may be a while on that one.

My First (and Last) Programming Language?

Somewhere along the line, I started reading Matt Jadud’s weblog because he talks about pedagogical issues with teaching computer science and I’m interested in this subject both from a personal and a professional standpoint. From the personal side, I spent several summers as a teaching assistant for Computer Science classes at the Talent Identification Program at Duke University and actually taught the introductory class one summer there. (TIP is a program that identifies bright teenagers using the SAT and gives them the chance to take advanced classes over the summer. It’s similar to CTY at Johns Hopkins.) Besides having fun teaching, the experience was also a fascinating problem to solve: how do you teach programming to non-programmers? Having picked up programming at an early age, it was a challenge to try and work out how to impart something that, for me, was very natural. It also helped that I assisted some very good teachers. From the professional side of things, I’m interested in how people learn to program because VB is explicitly designed to be an approachable language for beginners. So how close we do or don’t approach that ideal (and you can certainly argue that with me, if you like) is a big question for us.

A recent entry on Matt’s weblog referred back to an entry he wrote last year called “My First Programming Language(TM)”. Since I only subscribed in the past six months or so, I hadn’t seen it before but I’m glad he linked back to it because it had some very interesting thoughts about how programming languages should be structured for beginners. In particular, he talks about applying Joel Spolsky’s idea of leaky abstractions to programming languages by way of two generic languages named A and B:

In Language A, it turns out that you can’t say anything meaningful without reaching for other parts of the language. While we want to start off with simple bits of code, we must include bits and pieces of the full language to make even the simplest of sentences. Language B, however, is a complete core. We can do simple things simply to start, and if we want to say more complex things, we can. As we grow the language, we don’t have references out into parts of the language we don’t know; instead, we only have references back to the parts of the language we have already learned.

The inability to say simple things simply in Language A is a leaky abstraction. The inability to keep the complexity of the whole language under the covers kills us pedagogically (the blue arrow, below). What should we teach first? Where do we start to build a shared conceptual vocabulary that both the instructor and student can use? Where do we go next if we do manage to find a starting point?

What’s great about his discussion of these two languages is that it captures some of how we think about Visual Basic in a way that I don’t think we (or, at least, I) have been able to verbalize before. When designing new language features, we spend a lot of our time thinking about leaky abstractions and how to avoid them – without calling it exactly that. A good example of this is our design for partial types, which I’ve discussed here earlier. Partial types solve a particular problem for us: they allow us to abstract away automatically generated or templated code from user code. When designing the feature, we had to decide between two designs: one design required the abstraction to leak through into the user code (i.e. explicitly stating “Partial” on all parts of a partial type) and one design kept the abstraction separate at the cost of some explicitness (i.e. not having to specify “Partial” on all parts of a partial type). Each design had it’s advantages and disadvantages, but ultimately we came down on the side of the latter design because we felt it was more important to contain the abstraction, even at the sacrifice of some explicitness.

This does raise a deeper point which Matt references but doesn’t explicitly address. His entire discussion is organized around a split between a “Language A,” which is supposed to be leaky but suitable for “enterprise software,” and a “Language B,” which is supposed to not be leaky but suitable mainly for pedagogy (and not, by implication, enterprise software). The question is: why does there have to be this dichotomy? Why can’t there be a Language C that is designed to be both watertight in terms of leaky abstractions and suitable for writing “real” software? Indeed, our thesis is that Visual Basic does satisfy most of the traits of Language C, but we still end up spending a lot of time having the Language A/Language B argument anyway. Sometimes it’s like the old saying: “There are two kinds of people in the world, those who believe there are two kinds of people in the world and those who don’t.”

Volatile reads and writes in VB

Warning: Seriously geeky stuff ahead. May not be suitable for children or anyone who doesn’t love the minutia of JIT optimizations and the CLR memory model.

A reader, Russ, asks:

Given the importance of volatile in light of Greg’s comments here: http://blogs.msdn.com/grantri/archive/2004/09/07/226355.aspx. why doesn’t vb.net support a similar construct? or are we not allowed to write high-performance multithreaded code using vb? :p

The construct that Russ is referring to is volatile fields. C# allows you to declare field with the “volatile” modifier, which results in all accesses to the field being prepended in the IL with the opcode “volatile.” I’d like to pretend that I could adequately explain to you what volatile reads and writes actually do, but there is a high probability that I would get it wrong because the CLR memory model is not my thing. It is, however, Vance’s thing and you can check out a message he wrote that talks in more detail about the subject.

Although VB doesn’t support the volatile modifier, you’re not up a creek without a paddle. In fact, as I said above, marking a field as volatile in C# doesn’t do anything to the field itself – it just makes sure that the compiler prefixes all reads and writes with the volatile modifier. Volatility is really a property of reading and writing from a field, not a property of the field itself. In fact, there may be situations where you only care at certain points whether you do a volatile read or write, in which case the volitile field modifier is overkill (because it makes all reads and writes volatile). A slightly more ideal situation would be able to mark just a particular read or write as being volatile.

The CLR provides a way to do this, sort of. The type System.Threading.Thread provides VolatileRead and VolatileWrite methods that allow you to do volatile reads and writes from fields without having to do any declarative work at all. So, everything is right with the world, correct? Unfortunately, no. If you look at the definition of VolatileRead and VolatileWrite, they use reference parameters (ByRef) to refer to the field that you’re reading or writing from. This is necessary because if they were regular value parameters (ByVal) the VolatileWrite wouldn’t work at all and VolatileRead wouldn’t give you the desired behavior. (That’s because value parameters are copied onto the stack. That copy wouldn’t be a volatile read. When you pass the address of the value, then the VolatileRead method can do a volatile read of the value at that address.)

The problem is that when you pass a variable to a reference parameter, the type of the variable must exactly match the type of the reference parameter. If it doesn’t, then you have to create a temporary variable of the right type, copy the value into the temporary, call the method and then copy the value out of the temporary. This isn’t an issue for primitive types because there are overloads of VolatileRead and VolatileWrite for all the primitive types. But what about some random reference type like an array (which occurs in Grant’s example)? The closest overload is a ByRef parameter of Object, but that’s still not going to be an exact match. That means you fall into the copy-in/copy-out scheme I talked about a moment ago, which screws everything up because the reads and writes to the temporary variable are not volatile! Arrrrg!

So, are VB users just screwed? Fortunately, no. There’s another method on System.Threading.Thread that can help out here: MemoryBarrier. When you call MemoryBarrier before a write or after a read, you effectively make the read or write a volitile read or write. (In fact, in Whidbey this is how VolatileRead and VolatileWrite are implemented.) You could even write a generic VolatileRead and VolatileWrite to do this for you in VB 2005:

Function VolatileRead(Of T)(ByRef Address As T) As T
VolatileRead = Address
Threading.Thread.MemoryBarrier()
End Function

Sub VolatileWrite(Of T)(ByRef Address As T, ByVal Value As T)
Threading.Thread.MemoryBarrier()
Address = Value
End Sub

So, yes, VB users are allowed to write high-performance multithreaded code… 🙂

Recommended website: PInvoke.net

Matthias Benesch submitted a question asking if I had examples of how to use Win32 APIs in VB, specifically the API ReportFault. Searching on my site, I found that I’ve never actually mentioned the website http://pinvoke.net, which was an oversight. It’s a Wiki that the .NET community can use to trade Win32 API definitions for both VB and C#. I recommend checking it out when you have questions like this and, if you’re lucky, it’ll have an answer. (I also recommend submitting API definitions to it as well. Help out the community!) Unfortunately, it doesn’t seem to have a definition for ReportFault yet (and I don’t have one handy), so it doesn’t address Matthias’s question. Maybe someone will see this and submit it there in VB…

Back from the beach…

Things have been quiet around Panopticon Central while Andrea and I headed out to the East Coast to hang out at the North Carolina beach with my family and in Virginia with her family. We managed to get good weather all around, managing to avoid hurricane related storms and the like. So now I’ve got a few things to catch up on – after roughly a day of work, I’ve got my email down to under 100 messages, which is good but not perfect (I try to keep my Inbox at least under 20).

And Scott, before we add “ain’t” to VB, we’re at least going to add “y’all” as a statement separator. As in:

If x < 10 Then Y’all
    Return 30 Y’all
End If Y’all

I guess for the Canadians, we’ll also need to accept “eh?” as a statement separator as well…

Nice words for My…

Jesse Liberty has written a very nice article on My for O’Reilly’s OnDotnet.com. He starts with a theme we’ve seen a lot of over the years:

For a couple of years now, I’ve been touting the Microsoft-endorsed sentiment that it really doesn’t matter if you program in C# or in VB.NET, since both are just syntactic sugar layered on top of MSIL (Microsoft Intermediate Language, the true language of .NET).

But then adds:

That appears to be changing a bit with Whidbey.

He then talks about some of the features you’ll get with My. He concludes with:

The My object has made creating this application almost absurdly easy. […] VB 2 has taken a dramatic lead in Rapid Application Development with the My object.

Go check it out!