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

11 thoughts on “How do you do two mutually exclusive things at the same time?

  1. Anonymous

    Hey Paul,

    I fully agree. In fact I think all the changes VB.NET made were/are good changes, (with the exception of changing of Integer <g>) I think it’s important to state that, as many of the people supporting the VB6 petition do actually like Vb.NET

    I think the biggest problem VB6 code faces moving forward is indeed the underlying platform change. The individual language changes, such as Wend to End While make no real difference on the ability to move code forward. It’s more the cumulative amount of changes, especially the change in framework libraries that makes the task difficult and time consuming.

    But I think the real point is, there isn’t a need to upgrade to .NET. COM is going to be continued to be supported on windows for the foreseeable future. So rather than force people to upgrade, instead let them continue to code, and improve the ability to work with new features. (e.g. COM based Indigo and GDI) At the same time a new Vb6 could include options to make the code use Strict semantics, disallow non indexed default properties, require dates to be manipulated using the DateXXX functions etc. So code could be abstracted at the same time as being preserved. That’s how you achieve it.. two mutually exclusive things πŸ™‚

    Reply
  2. Eric Lippert

    A pri-2 goal was also to be as backwards compatible as possible with VBScript. John H and I spent many a crazy hour trying to figure out how to make the wicked combination of VBScript’s Eval/Execute methods and VBScript’s loose typing rules work in VB.NET. We came up with a new kind of variant that we called a "deviant" that had the right semantics, but its implementation requirements and performance characteristics were both godawful. It totally broke the "pay to play principle" — we would wreck mainline performance for the sake of some bizarre and unlikely backwards compat scenarios.

    Fortunately sanity prevailed. I’m not completely happy with how VB.NET turned out as far as compatibility goes, but most of the compromises were pretty reasonable.

    Really you’ve got to think of it as a whole new language designed to be easy for VB6 programmers to learn — it is _not_ "VB7", and our failure to message that effectively has caused a lot of FUD.

    Reply
  3. Bill McCarthy

    Hey Eric,

    Exactly ! VB.NET should be viewed as another tool, not a direct replacement. There are of course synergies, and it’s these that should be highlighted and enhanced. You highlighted one such synergy, the focus on easy for Vb6 programmers to learn. If product support for VB6 development tools was actually to continue, the opportunity to highlight more synergies would be there, especially if in the same IDE. The 2 are different languages, different tools, but there are areas where the two can meet and work together. That’s what has been missing.

    The current approach is to drop VB6 tool support and pretend that VB.NET is the replacement. That’s wrong, as you correctly pointed out. We, as a community, need to focus on the two working side by side, enhancing synergies, sharing and growing together.

    Bill.

    Reply
  4. Jonathan West

    Hi Paul,

    Way back when the original beta and all the various code-breaking changes were being discussed, I commented that of all the changes that were discussed at the time, three had a reasonable technical justification from Microsoft in terms of platform compatibility. These were:

    1. The change from deterministic finalization to garbage collection

    2. The loss of default parameterless properties and mixed Get/Set assignment for the same property

    3. The loss of mixed-accessibility properties (though this is returning with VS2005)

    I can see the points on both sides of the argument as to whether these platform changes were a good idea, but let’s accept for the purpose of the discussion that they all were. Since the capability of the platform is different, I also accept that is also appropriate to make such changes to syntax as are necessary for compatibility with these changed capabilities.

    In the case of #1, no change in the language syntax was strictly necessary as far as I’m aware, the change was only the behaviour of the application (i.e. the order in which objects were torn down) and in the addition of new methods to enable you to force garbage collection.

    With regard to #2, while a class could no longer have both Set and Let property assignment routines, there was no particular need to drop the Set keyword for assignment. If you had wanted to make it as easy as possible for VB6 code to migrate, it could have been left as an optional-but-unnecessary keyword in object assignment, in the way that Let has been for value assignment for very many versions of Basic. It would also have been possible to allow "Property Set" and "Property Let" both to exist in the language (but not in the same property) meaning the same thing in the context of the new platform, perhaps with a compiler warning to the effect that the Set keyword is being deprecated. A property that had both Get and Set assignment would throw a compiler error.

    As for #3, you went and changed the whole syntax of properties in classes, and now the syntax is having to go through some hoops in order to reinstate the capability that was there before. So where in VB2005 you need this for a minimal mixed-accessibility property(taken from Matthew Macdonald’s article on new features in VB2005)

    Public Property Status() As Integer

    Get

    Return _Status

    End Get

    Friend Set(ByVal value As Integer)

    _Status = value

    End Set

    End Property

    VB6 had this for the same functionality

    Public Property Get Status() As Long

    Status = _Status

    End Property

    Friend Property Set(ByVal value As Long)

    _Status = value

    End Property

    The VB2005 version is 2 extra lines, the Friend keyword is that much less obvious as it is indented relative to the Public keyword at the start of the property, the whole thing is a bit less readable, and old code snippets can’t be pasted in without rework.

    If the original VB.NET had retained the old property syntax, then if the Get and Set had different status (e.g. one was Friend and the other Public) the compiler could have thrown an error. With the re-introduction of mixed accessibility, that restriction could simply be removed.

    Subject to the restrictions I have described above, the original VB6 syntax could have worked perfectly happily with the new platform, and "platform compatibility" gave no justification for these changes.

    There were literally dozens of such syntax changes, each one of which made it that much harder to move code from VB6 onwards. That is why there is such a lot of hubbub about the loss of VB6 and the lack of a forward path for VB6 applications.

    It would appear to me to be in Microsoft’s own best interest to find a way of retrieving this situation, if only to encourage VB6 developers to continue to use (and pay for) Microsoft’s current developer tools and increase the adoption of Microsoft’s latest platforms.

    The first thing that is needed is a common understanding of Microsoft’s policies regarding what justifications there are for making changes to languages that cause old code to break. This would give confidence both to the VB6 developer community and also those who have already adopted the .NET languages and who may be wondering whether their code will break next time you change platforms.

    Reply
  5. Bill McCarthy

    jonathan,

    Although the code you posted is actually in-correct, you are missing the big picture here. The block property declaration in VB.NET is indeed an improvement.

    Some things to note:

    First, the block skeleton is completed for you, so in fact you type less code in VB.NET than VB6.

    Secondly, because you do not have to write the property name twice, you don’t get the problem where a Set name might not match a Get name, hence giving two properties instead of one.

    Third, in VB.NET you don’t get to make the same mistake as you just made in the code you posted, because of 1 & 2 above.

    Fourth, maintenance is vastly improved because you can see there is a Set and or a get there… you don;t have to scroll all the source code, instead this is logically provided for you.

    Five. The conversion wizard updates all code perfectly for this new block construct

    Six. There is a insert code snippet wizard that modifies code to the new syntax for sample code posted from the web etc.

    So in summation, this was and is a great forward moving thing to give to VB.NET.

    Oh, and before you ask, if you were to allow both syntax then you are taking away the advantages of three and four above, hence having a negative impact on VB.NET code.

    So reality is, the right decision was made here. It is NOT a barrier for existing code, and it addresses problems like your own post demonstrated πŸ˜‰

    Reply
  6. Bill McCarthy

    Hi Jonathan,

    Well as Paul said to you in Jay’s blog, this has been debated between you two adnauseum, so I thought you might actually want to hear from someone who uses both VB6 and VB.NET as to what this change really means.

    Anyway Jonathan, the facts are the facts. It really shouldn’t bother you who tells them to you.

    Reply
  7. Pingback: Anonymous

Leave a Reply