Part II: A Direct Response


For starters, I just want to say that this statement on .NET 5.0 seems ill-timed. The nature of the message contrasts in a very unflattering way with the kind of reassuring supportive messaging other companies I interact with have been putting out during this time of worldwide crisis. I can only hope that this timing is a coincidence and not any intentional decision to take advantage of a social media trend and a news media cycle currently preoccupied with an admittedly more important global pandemic.


Next, I want to address some disingenuous language you’ve sprinkled in here and some other language not used but evoked here which I’ve heard floated in the last year or two in places, testing out reactions.

The idea that Visual Basic’s “stability” is “valued”. Well, of course! Everybody enjoys stability. It’s kind of part of the Microsoft brand. What exactly is the implication here, that … if we add one more feature to VB.NET… the users will rebel and… leave? To C# (and you desperately want to prevent that)? To Java? What? They’ll stop upgrading to VS for fear of new features creeping in? And at a greater rate than those who won’t upgrade because they have no reason to? They’ll rebel more than they do when you tell them you’re not evolving the language anymore? How did you do the math on that? Was there a survey!?

“The most important thing is that it keeps doing what it’s been doing”

Was instability on the table? How does this contrast with the other .NET languages? Is that the new C# tagline? “C# – breaking stuff, all the time”. “F# – too bleeding edge for compat; the F stands for free-and-loose”. It’s a meaningless thing to say because for its entire life since 2002 the evolution of VB.NET has been concerned with stability and compatibility, like all of the .NET languages.

This is like when discussing hiring from underrepresented groups someone says “But of course the most important thing is that they’re qualified!”. It’s disingenuous. It prefaces or excuses the inexcusable by putting it next to a statement that’s universally considered sound and positive but the impacts of the thought next to it are anything but sound and positive.

This is made more inappropriate by the fact that, as I point out here, the .NET Team (no quotes) is generally not part of the VB.NET community. You, a group of people not in my ingroup, telling me what matters to me and then using that thing you told me I value to discount my opinion is condescending and inappropriate. It would be so in every other context and it’s still so here.

“People aren’t clamoring for new features”

You have numerous channels for user feedback where currently and since its inception, members of the VB community have and do communicate constantly their desire for evolution in language and tooling because that is also valued.

Again, it’s like someone saying “But the biggest contributor to carbon emissions is going to be the industrialization of China and India, so nothing we do matters anyway”. They’re not putting that cherry-picked fact forth because of their genuine heartfelt commitment to disseminating objective truth but because that particular truth doesn’t ask anything of them today. It allows them to keep doing what they’re already doing. And this narrative you’ve constructed about stability and compatibility is an equally disingenuous notion that doesn’t ask anything of you.

More Inappropriate

If you look at the F# language suggestions repo there’s a section on the design process. And in the section on new features it says this:

“Stability is a virtue”

Stability is valued elsewhere and yet F# marches on. They didn’t need to make a sweeping statement sandwiched in the middle of a post on how “F# planned to be in next release of Visual Studio”. They just keep the language stable because that’s leadership.

I worked on VB.NET for 8 years. I never needed to make a sweeping statement about evolution in general to be responsible, keep it stable, or compatible. I’ve personally argued against or killed plenty of unnecessary features that were only proposed because that feature was going into C# but just didn’t make sense in VB, wasn’t needed, or broke compat, etc.:

  • Expression-bodied properties & methods?
    Stylistically inconsistent, waste of time; long tail of follow-up asks to make it consistent.
  • Primary constructors?
    Wrong design for VB.
  • Deconstruction statements?
    Too early to tell given named tuple elements.
  • Declaration expressions?
    Didn’t fit.
  • Async void?
    Didn’t need it, tried to kill it and failed.

So, for instance, when thinking about “evolving”, what about a feature like Await being allowed in Catch & Finally blocks? It’s a feature I know customers clamored about when it was cut from VS2015 due to the unplanned schedule contraction detailed here. Logically, it was an approved and desired feature that should have rolled over to the next release but didn’t make it and should have rolled over to the next release after that and still hasn’t made it.

If right now you’re thinking “Oh! Forgot/didn’t know about that”, it indicates to me that you’re probably not the body who should be making sweeping statements about the language’s evolution.

When the implementation of ref returning methods was too invasive and incoherent with the VB design I proposed a tailored subset and then accounted for that decision publicly. I signed my name. As I did on every feature request on Connect, UserVoice, or GitHub that I’ve ever responded to across hundreds of customer interactions. I know Mads has been similarly accountable for C# and Don accounts for F#.

The “The .NET Team” attribution on this post illustrates precisely the lack of accountability when there isn’t a VB Team that I describe here. Who is “The .NET Team”? If I have questions, who do I reach out to? If we’re at a conference do I just walk up to anybody and start talking? If this decision turns out to be really bad, who is held accountable for it? Do we just get a whole new “The .NET Team”? Like, all of you?

I suppose that it’s consolation that you didn’t scapegoat Kathleen on this one. I watched her tirelessly advocate for VB, including thoughtful language evolution for 8 years. We don’t always agree but she’s been fighting this fight longer than I have. We know how long she’s been at Microsoft and I’ve seen what happens when newer PMs take the fall for other people’s decisions so I’m glad at least that you didn’t drag her name through this mud pit you’ve created.

You should be able to articulate the principles, the design patterns, and the style of the Visual Basic .NET and how any potential new feature caused by anything either fits or doesn’t fit into that style, or is incompatible. And if don’t feel capable of that then you definitely aren’t the body that should be making sweeping statements about the language’s values and evolution.

You’ve presented this blurb couched in language which suggest stewardship with intention and thought when it precisely promises the absence of thought and the absence of intention. This post is illustrative of precisely why leadership of an open source language from people outside of that language community is wrong.

More Disingenuous

But let’s go back to my example of Await in Catch/Finally; a feature which illustrates that this statement isn’t the result of a shift in thinking but attempt to normalize or rationalize a system which is already horribly broken.

It’s a feature we (because I was there) costed at about a week. It had been done for C# already but had to be cut in VB due to a schedule change. It’s a known quantity of low cost that adds no new syntax to the language, probably has no IDE work, and actually makes the language more consistent. This would otherwise be the least controversial addition to the language. This lowest hanging fruit has been out of reach for 5 years.

Now let’s take something that was done. In VS2017 Visual Basic, like C#, received updates after RTM. One such update was non-trailing named arguments. A great feature that makes VB code more descriptive. The problem is that as an out-of-band feature, in order to use it you had to update the project language version to 15.5. No UI for doing that. No dropdown in the project properties.

So, you’ve somehow worked yourself into a situation where you’ve not only been unable to deliver small, well-understood features, with no new syntax or conceptual burden, that were already agreed upon and promised, but you’re also unable to ship any UI to enable customers to use the new features you have added. Which is an indictment of your process. The only thing that’s changed here is whereas before you were unable or unwilling to account for missing features, now you don’t have to.

Continuing on this thread, in C# there was a quick-fix (a feature pioneered in VB) to update the language version from within the editor. It made 150% sense for VB, but required an API change within the bowels of Visual Studio to pass some information from one service to another in order to make that fix possible. But the bureaucracy made even that impossible. The only option for VB users was to unload the project and manually modify their project file: the most un-VB experience ever.

And in VS2019 you cut temporary “zero-impact” projects, a feature that QuickBasic, VB6, and VBA all have and most other Microsoft products have an analog to. I open word, I can start drafting in a new doc without saving to a particular location. I can even work on VBA macros without saving. Same with Excel, PowerPoint, Notepad, Paint, etc. It’s an established paradigm.

Speaking directly to my point about whether a C# body can understand, respect, and defend VB experiences: this feature was specifically added back to VS2005 after massive feedback from VB users that creating “ConsoleApplication238” was a big takeback from VB6. It was available to C# for years but off by default and on by default under the VB profile, including the very successful VB Express Edition.

I literally use this feature every day: Spinning up temporary projects to help other VB users on the Internet. Do you know how many throwaway projects one makes in a day answering questions on VB Facebook groups? VS2019 literally broke one of my critical workflows and you weren’t even slightly apologetic. You didn’t care about stability or compatibility or the spirit of VB then. But what you probably cared about was NuGet and that zero-impact projects didn’t support it, and you didn’t want to do the work to make that happen, and so dismantling a core VB experience of 12 years was an easy decision for you.

So, here’s my problem and why this post lacks credibility as any genuine stewardship from the thoughtful “good guys” you try so hard to present yourself as with these crafted words. It is evident that you don’t truly understand, respect, or care about VB’s unique qualities or vantage point. You only use its uniqueness and its style as a bludgeon weaponized against its community: a nebulous reason to do or not do whatever you want. Which, again, is an indictment of a process where C# developers lead the VB language.

You can’t (for systemic reasons) or don’t want (because you’re not VB developers) to work on VB. I also don’t want you working on VB. It’s demonstrably harmful and it was harmful long before this statement. Far more harmful than whatever “stability” or “compatibility” boogeymen you’re protecting us from. But there is a working model for liberating yourself from that responsibility that doesn’t involve hurting me. I want you to be only as involved and concerned with VB as you are and have always been with F# and through the same means. I’m sure they equally thank you for that level of autonomy.


“The .NET Team” is effectively a body of C# developers. C# developers should not be making sweeping declarations on the future of VB.NET because none of them have to live with those decisions. You’ve attempted to present a narrative of stewardship under the color of legitimacy but your statement on “Visual Basic support planned for .NET 5.0” is replete with questionable timing, questionable reasoning, questionable plans, from a questionable source with questionable history and just a general display of questionable judgement. The current system is broken and it’s failed. And your statement is not the solution to that brokenness, it’s just the latest symptom.

When you’re doing something righteous, well-reasoned, and that reflects honorably on you and your company, no one will be suspicious of why you published it in the middle of a global pandemic, and you’ll feel confident enough in it to sign your name.

-Anthony D. Green

Preface | Part I | Part II | Part III | Part IV | Part V: An Open Letter to Satya Nadella

Comments have been disabled for this post. If you have feedback on this topic specifically it belongs here, on the .NET Blog.

Part I: A Fundamental Right to Self-Determination

In 2014 Microsoft open-sourced Visual Basic .NET as part of the “Roslyn” project. For its entire life before that VB (both Classic and .NET) had been a closed-source proprietary language. And in a timeframe where standardized languages and open source languages were establishing themselves as the new normal, VB caught a lot of flack for that. But regardless, it was a product. The owned product of one company: Microsoft. Some people buy it, some people don’t. It sucks if they stop making Twinkies but Twinkies are a product produced by Hostess.

But, when Microsoft “hit the button” on pushing that code to CodePlex (later moved to GitHub) with an Apache license they fundamentally changed the nature of what Visual Basic .NET was. It is now an open source programming language. Not a product in a portfolio.

And every community of an open source programming language, by definition, has a fundamental right to self-determination. That’s the whole point. It’s implicit in the right to fork that the community has an interest in shared ownership with the project leaders (not owners). It’s got a whole “consent of the governed” vibe to it. It’s why they’re called benevolent dictators. It’s why Don Syme styles himself nobly as a contributor, not a puppet-master. If there isn’t a right to self-determination what does it even mean to be open?

“You can work on exactly what we say in accordance with our roadmap which is dictated entirely by us in our interests based on our priority, capacity, without your input or consideration for you and don’t even bother thinking about or talking about anything else because it ain’t gonna happen, nuh-uh it’s been decided already” isn’t open source; it’s just free labor.

Further, the open source model only works because the project leaders are part of the community. They don’t sit outside and above it. Linus isn’t a Windows community member. The folks calling the shots on Python aren’t predominantly Lua developers. Don may be a phenomenally brilliant F# developer, with years of knowledge, experience, and technical skill that enables him to lead the F# language but he derives the legitimacy of leadership because he is an F# developer. Same goes for the rest of the F# team @ Microsoft. Only when project leadership is part of the community does that leadership uphold the fundamental right to self-determination because they are part of the self.

The open-source programming language VB.NET’s developer community likewise has a fundamental right to self-determination and satisfying outsiders cannot be a perquisite to self-determination, by definition.

A peculiar quality

This is a writing about Visual Basic, specifically VB.NET, and a peculiar and seemingly unique relationship it seems to have with the rest of the programming world and particularly with its sibling language C#. I’ve wanted to write an article for a while on toxic behavior in the programming community in general, and specifically in some parts of the .NET community. This writing touches on that subject but I’m going to try to keep it focused on the role a particularly toxic instinct should not play in this discussion or really any discussion about VB.NET. The unique quality of VB is this:

Visual Basic .NET is (to my knowledge) the only programming language on whose community other programmers who are not part of that community feel entitled to an opinion or need and that that opinion or need carry equal or greater weight.

This is particularly true of C# developers and all the more dangerous because of the disparity in size between the two communities. And because the “The .NET Team” in Microsoft consist almost exclusively of C# developers (with notable exceptions on Roslyn), I’m including them in the broader C# community.

Unsafe spaces

Whenever there is any discussion between VB.NET developers in any shared space, on a blog, on a mailing list, on Twitter, in a presentation, in a meeting room, there is almost invariably a C# community member who not only has an opinion on VB.NET and VB.NET developers but feels obligated to share it on equal footing and with equal weight to the members of the VB.NET community and the presumed, ingrained expectation that that opinion be respected.

This is not normal. Java has existed for most of my life. It would never occur to me to pop up on any blog post about Java at all and say anything, especially anything negative, about Java developers. What’s Ruby up to these days? I don’t know. When someone tweets about JavaScript there isn’t any foul impulse swelling within me that just has to escape. I’ve never seen a VB.NET programmer make a sweeping, offensive statement about F# developers or their feelings about the future of the F# language let alone present that statement as if it’s a legitimate contribution to a discussion about F# or within that community.

What I love about F# and have observed inside and out of Microsoft is that most people seem to think they aren’t smart enough to contribute in any way to a conversation about F#. It’s a multi-paradigm language with all the same features and capabilities as C# but they just can’t reason about it. They are quiet and humble because they’re afraid they’ll open their mouths and say something about something they don’t understand and look bad. At worse they’ll say “that looks confusing” and just sort of wander off. They don’t hijack the conversation.

Ex-officio my role as VB language PM, I sat on the C# design team for a while (just as I asked the F# PM to sit on the VB design meeting). I had opinions. I offered suggestions. But I never advanced the idea that I was more than a guest in that conversation or that my feelings about the design of C# or certain features were important; because I’ll never have to live with the definite assignment rules (that I dislike).

Yet on the matter of VB.NET there are seemingly hundreds of thousands of C# developers waiting in the wings at every turn, dying to make proclamations and it is exhausting and toxic and literally leads to VB.NET developers simply not participating in mixed-company settings.

I’ve tried to create or maintain “safe spaces” for VB.NET whether that was the team blog, or the MSDN forums, or the separate vblang repo because I’ve seen how just by virtue of numbers even the most well-intentioned C# voices drown out the VB.NET ones. There was a fairly active VB mailing list I was on for years. Plenty of VB discussion. Sometimes positive, sometimes a little heated, but active. And when we elected to merge that list with C# and F# to create a unified “.NET list” I watched the VB voices just fall silent after every time one of them spoke on a VB matter 5 non-VB programmers would jump in. When it comes to VB, everybody wants to contribute their own fears, uncertainties, and doubts, and the deluge from the larger numbers is stifling the voice of the actual community members.

A big part of the reason I don’t engage on Twitter as much is because for any VB related tweet there’s high percentage chance (too high for me) that some non-VB developer will see that as their invitation to shape the conversation about their feelings. “I feel VB developers are old, fight me or I won’t stop tweeting you!”. “I’m not a VB developer or haven’t used it for years so I don’t really care one way or another, but, I saw this tweet/blog and thought it was my opportunity to take up time, space, energy, and oxygen”. “I’m happy for your performance numbers, and Imma let you finish, but how do you explain these CareerBuilder numbers for VB.NET jobs in my state? Do the data science for me and you can continue having thoughts or enjoying things”.

Check your privilege

A few years ago, a VB MVP made a rather controversial comparison. It was provocative and more than a little offensive so I’m not going to restate it, but in my own time I have come to an observation which quite unintentionally evokes a corollary:

C# developers are the privileged majority group of .NET developers.

When I say this, I don’t mean “most of .NET is C# developers”. I mean that if you look at the behaviors of privileged subpopulations in “the real world” (pick your analogy), the C# community exhibits an alarming number of parallels to certain negative behaviors of those groups. I don’t know if having lived my whole life as a Black man makes me hypersensitive to these parallels or if others have noticed this too.

I say all of this to ask, if you’re not a VB.NET developer, and especially if you’re part of the C# community to keep in mind the fact that you are outside of the VB.NET community. This isn’t about you.

If you want to show support, show support. But outside of that, have respect and humility for the fact that the people impacted by these decisions should be the people shaping the discussion around the decisions. You literally have no skin in the game.

  • It’s not incumbent on us (VB.NET developers), to convince you (C# developers) that we actually experience pain for you to stop doing thing things we ask you not to do because it’s offensive.
  • It’s not incumbent on us to convince you that we’re smart enough to do anything.
  • It’s not incumbent on us to convince you that we will succeed at open source in order to be allowed to proceed with our already open-sourced language.
  • It’s not incumbent on us to convince you that we like the web or mobile.
  • It’s not incumbent on us to convince you that we hit “New Project” often enough.
  • It’s not incumbent on us to show that we switch jobs often enough to keep up with the new skills.
  • It’s not incumbent on us to prove that there are any new VB.NET programmers coming into the world (there are).
  • It’s not incumbent on us to prove that the apps made by the new programmers are real enough or complex enough or connected enough or have enough concurrent users or generate enough revenue or sales volume.
  • It’s not incumbent on us to provide a map to all of our social communities on every site and every IRC channel in every language so that you can survey them to see if the activity level meets your idea of living.
  • It’s not incumbent on us to convince you of particular year-over-year growth numbers projected out over five years for you to allow us to continue being.
  • It’s not incumbent on us to program how you program or how you want us to program or to adopt technologies at a rate you find sensible in order to justify being left to our own devices without interference.
  • It’s not incumbent on us to convince you that VB really is distinct enough from C# to justify us having a preference at all (in 58 pages or more).
  • It’s not incumbent on us to describe a physical impairment that keeps us from technically just using some other language.
  • It’s not incumbent on us to disprove your stereotypes about us regarding race, gender, age, or anything else for that matter in order to earn the right to be respected.
  • It’s not incumbent on us to provide a logical proof to you that you’re being disrespectful in order for you to stop doing it when asked.
  • It’s not important that you are happy or unhappy that we exist.
  • It’s not important whether you know or have met 5 or more of us personally.

So please, when you’re tweeting, or leaving comments, keep that in mind. And keep in mind that while each of you may have a thousand questions, and that it could even be education or fun to answer some of them, the answers to those questions are not actually relevant to the discussion because You. Are. Not. Us.

Forking isn’t success, it’s failure

This is not a decision that needed to be made at the VB.NET community. It didn’t need to be made for the VB.NET community. It didn’t need to be made at all. We have a fundamental right to self-determination that ought to be recognized and respected unencumbered by the fears, uncertainties, and doubts of individuals who are not part of this community in any way and do not have to live with the consequences of these discussions at all. VB.NET is no longer a product, VB.NET is an open source programming language that needs to be led by people who are actually VB.NET developers: the few within Microsoft in concert with the many more of us without. I’m not writing this as some prelude to a defiant fork; I really want to avoid that. If someone on “The .NET Team” doesn’t get why, they don’t understand open source as well as they think they do. This language needing to fork (if it comes to that) isn’t an example of Microsoft succeeding at open source; it’s failing.

-Anthony D. Green

Preface | Part I | Part II | Part III | Part IV | Part V: An Open Letter to Satya Nadella

If you’re leaving a comment on my blog, sending me a contact request, or tweeting at me right now…

know that I have not and can neither read your message nor reply for a while. Here’s why [Trigger Warning]:

I’ve started to talk a little more about this in the last few years and I try to be transparent about it. I have a mood disorder. I have major clinical depression. I have anxiety disorder. I’m diagnosed. I’m being treated. I’m still not OK and may never be. This isn’t about VB, or my professional life, or what’s happening right now so don’t worry; this IS NOT “making it worse”. I’m NOT reacting in any particular way because I’m struggling with mental illness but regardless, I am still struggling.

[EDIT: This post has been edited since my initial publish due to some touching but perhaps unnecessary reactions. Please see new section below!]

It’s painful, stressful, and usually takes a tremendous amount of willpower for me to participate on social media under normal circumstances. If you follow my Twitter account, you’ll see that I don’t tweet very often. On a very good week it’s a few a day. Even my best, most well received blog post creates agonizing anxiety immediately after. Every time you see me write a bunch in a burst and then disappear for weeks or months it’s likely because I’m going through some form of depressive episode and can barely find the strength to get out of bed. I’ll tell you more about this sometime.

There’s so much toxicity in the world. And toxicity in general from programmers. Toxicity from non-VB programmers. Toxicity from C# programmers specifically. Toxicity from some VB (6 & .NET) developers. And just plain second-hand stress from VB developers who, while not necessarily toxic, are rightfully venting frustration, despair, and anger. I get it and I am so honored and flattered that VB community members trust me enough that they still feel I’m the person to come to when they’ve got concerns but sometimes it’s a lot for me to absorb.

So, I’m aggressively guarding my emotional state right now.

If you’re trying to say something positive, commiserative, or supportive: Thank You! I swear it means the world to me to hear from you! It helps me stay positive and connected to the world.

If you’re trying to say something awful or insensitive to me right now, please don’t. Consider just not saying anything at all right now, anywhere. And if you absolutely can’t hold back then leave that type of commentary on the .NET blog so they can see what type of person celebrates their choices.

If you’re upset about this, I get it; me too! But know that I’m not the one who needs to hear that. Make sure you’re sharing that feedback however you feel it directly to Microsoft and its representatives.

I promise I’ll read all your comments, messages, and tweets in a little bit (days). I just can’t risk reading the wrong thing from the wrong person right now when I need to keep my energy and focus on speaking up and speaking out.



[EDIT: It has come to my attention that some readers may have read this as me saying that right NOW is one of those times that I can barely get out of bed. It is NOT. I’m up and about. August-October was very rough but I’ve been slowly rebuilding to a better place for the last few months (I’m cleaning my apartment again!). I just meant that in general, this is a thing to be aware of and that even when I’m feeling “better”, I still have to be very intentional about when and how I engage to avoid emotional disruptions that won’t last months or weeks but can still last hours or days.

I hesitate to use the phrases “I’m OK” or “I’m fine” because I’m so used to saying them and realize now that they set certain incorrect expectations. It’s akin to a diabetic who’s taking insulin saying “I’m not diabetic anymore”. No, you’re still diabetic, you still have to treat your body in a certain way, you still may not be able to do some things, you’re just not slipping into a coma currently. I’m not “OK” like “back to normal”; I’m not “normal”. But I’m also not in free fall or backsliding right now.

Thanks to my friends and loved ones for reaching out! Don’t be alarmed.]

A Primer on Why the Chronic Suffering of the VB.NET Community is neither Necessary nor a Matter of Expense or Practicality

I’d originally planned to write on this particular topic in response to increasing outreach to me personally, through my blog and other places, unsolicited, and independently from multiple community members expressing concerns about the health of VB.NET but also their passionate and heartfelt desire and commitment to contributing to its success. I too had been thinking about this, spurred on by comments on the vblang repo, social communities like forums, Facebook and Twitter, but also my own experiences and limitations. Due to recent announcements I’ve had to edit this post somewhat but fundamentally it still makes the point I always wanted to make; what’s changed is the context. It’s not a hastily written result of a last-minute brainstorming exercise or an emotional outburst but the culmination of my thoughts and observations over the last 10 years, 8 of which were spent working on VB.NET at Microsoft. It’s not at all my complete take on the current state of affairs but it is critical for the entire VB.NET community and everyone else watching to be armed with this context when discussing or socializing about anything else, so, I’ll try to provide that first and roll out any further points separately.

Time and time again I see the discussion of Microsoft’s level of investment in VB.NET framed around the same faulty assumption: it’s just too darned expensive and impractical for Microsoft to support two .NET languages (ignoring the fact that they actually make three); it would take an army of developers and content writers at great expense nearly duplicating all effort across the ecosystem at worst or perhaps 10-30% of the (Developer Tools) division resources at best. Today I want to put that misconception to rest.

The difference between where we are now, a position of continual disappointment, dissatisfaction, lost trust, stagnation, frustration, and humiliation; and a place of continual progress and increasing developer satisfaction for the VB.NET community IS NOT AN ARMY of redundant, reluctant, overworked, overcommitted Microsoft employees. Everyone needs to get that out of their heads that that is what this is about—that it’s fundamentally a choice between purgatorial misery for an entire community and hamstringing 5, 10, or 30 of the .NET organization or DevDiv and tens of millions of dollars in salaries. The difference between where we are now and a mostly HAPPY sustainable VB.NET community is…

3-5 developers.


That’s all. Not an army. Not a percentage. Not millions of dollars. Less than a handful of folks in a team room is enough to *radically* invert the delays, shortfalls, perception, and “forced tough decisions” narrative many of you have observed in the last few years. We know this to be true because we’ve seen it working for 10 years and I’m going to explain it and how we got here so that we all have the facts for thinking about our own next choices and Microsoft’s choices. None of this suffering, depression, and contention is necessary AT ALL. Nothing that’s happened (or not happened) in the last 5 years is about cost or practicality; and malice is not required to explain any of it either. So, let me walk you through the rude Q&A.

How could 3-5 devs make any real difference?

I’ve said that a wildly different reality could easily be achieved with a small autonomous dedicated team of 3-5 people. I know this because we’ve all been watching it work significantly better for TEN YEARS on the F# team. I’ve seen in arguments people say “C# and F# are clearly the priority because…” when for the better part of the last 10 years—it’s entire productized life—F# has had on average 2-4 devs working on in at any given time (and a few times a little as 1) as a whole across the entirety of the company. Full stop. And what has that gotten them?

All of this value in just 3 years, update after update, release after release, continuously, and transparently delivered by a small agile team of usually less than 5 people. Have they had setbacks? Absolutely. At times they’ve been outright excluded from certain technologies and at other times they’ve been perilously understaffed due to attrition but on the whole their users have seen steady progress, leadership, and accountability. They love the product, they love the team, and they’re happy to roll up their sleeves.

VB.NET is an order of magnitude larger than F# but externally people have a wildly disproportionate perspective on it because of the results it can produce because it operates as a separate team from the broader C#/VB/.NET org. At times F# hasn’t even been in the same org as C# at all. Yes, open source is a significant part of that success so I’ll get into that next.

And beyond open source, as a point of comparison, all the tooling support for VB.NET for Windows Phone 7 was implemented and tested by 1 engineer, on the side. The OmniSharp work that lights up C# experiences in VSCode: for quite a long time was just 1 engineer. All of the Windows 8.x samples: 1 engineer. Don’t underestimate the impact 3 developers could have.

“But F# can achieve so much because of its engaged open source community; VB.NET doesn’t have and likely can’t have so vibrant an open source community because… <stereotype>”

F# absolutely leverages its open source community. But a few things to keep in mind. Fostering that community is and has been a top priority of the F# team and that’s something that they’ve been able to do because of their autonomy and they started doing it long before it became popular and VB and C# open sourced. And, I can tell you, having been in the sprintly status meetings where we discuss open source commits and contributions that they would consistently put Roslyn to shame despite the C# and VB communities both being significantly larger (in fact I think VB support in .NET Standard/Core 2.0 was done by an F# community member).

And this is usually when some dudebro in the back stands up and says “But the average VB.NET developer isn’t going to contribute to open source—they <condescending stereotype>!”. Well, yeah. The average C# developer isn’t going to contribute a compiler feature or any feature. The average F# developer isn’t contributing. Open source communities aren’t about average users. VB.NET has more than enough above average folks who want to contribute and have tried to contribute but that desire has to be grown and supported by a group of folks who treat it as a priority. For quite a while (felt like years) I watched the just 2 folks on F# at the time: Kevin Ransom and Lincoln Atkinson where most days all they did was work with their community on PRs and keep the lights on with basic infrastructure or platform work for F#.

“But who would really contribute?”

We’ve already had engaged potential and actual contributing VB.NET community members:

  • Adam Speight was one of the first community contributors has made contributions in the compiler and the IDE and prototyped new features.
  • Paul1956 took on work to enable comments after line continuation.
  • Eric Mutta has tried to make contributions in a number of areas.
  • And others have reached our repeatedly both while I was at Microsoft and since about contributions not only in the compiler but the IDE and in documentation and in tests and in partner tools like the EFCore code generator or just templates and samples.
  • Current and Former VB MVPs (some now Microsoft employees) have gotten their hands in the code and produced or started to pursue viable ideas.
  • Former VB team members who have moved on from Microsoft are out there in the wild, including…
  • Me. I am literally a VB community member who has actually written features and product code that ships in the VB.NET product today. VB String interpolation is a feature `$”Written by: {Me}”`. I implemented the initial parsing of `Async` and `Await`. I’ve written Roslyn APIs that power IDE experiences. I implemented the `TypeOf … Is|IsNot`, I’ve prototyped features in the product like multi-line string literals, readonly auto props, byte literals, year first date-literals, and others. Last year I literally prototyped and demonstrated several feature ideas including writing VB code that runs on Android and in the browser without any extra support from the Xamarin tools or ASP.NET Core teams. I am a PURE VB.NET developer. I have never used any other language full-time for any significant portion of my education or career—a client project here or there but nothing that somehow made me NOT a VB developer. How am I supposed to engage?

But a culture of contribution doesn’t succeed in a vacuum. As one VB.NET community member noted to me (last month, I think): (paraphrased) “I normally contribute to making the docs better but seeing the stagnation in the vblang repo makes me not even want to bother doing that”. It’s not a set of individual dials but an ecosystem and the impact of failing in one category discourages all the others.

F# has between 5-15 BIG contributors and a long tail of smaller contributors. I think there are more than enough VB.NET willing and capabledevelopers in the world who could meaningfully contribute to the VB.NET ecosystem if they had 2-3 engaged team members inside Microsoft treating both VB.NET and open source as their first priorities. It doesn’t mean we’d get “everything”; it doesn’t mean that “everything” has to be accepted, but there would mean more blog posts rich with content like what F# has when a new release comes out and less radio silence and excuses.

F# wasn’t born flying with open source, they had to crawl. And supporting their community is a great example of a priority they can make because they’re autonomous and I’ll explain why autonomy matters next.

Why what we’ve been doing stopped working and why you don’t have to assume it’s because Microsoft is anti-VB.NET

The thing about Microsoft—a large international trillion-dollar mega corporation made up of over 100,000 people, many of them quite smart, and quite busy is…

There is bureaucracy there that does not sleep

I’m going to tell a few stories, buckle up.

First story. In 2005 (I think), the VB team, in response to community feedback that the solution explorer was overcrowded with items and visuals which weren’t directly user-created, decided to hide the References node. VB has its own reference management property page (which also manages project-level import directives) so this was technically safe to do. But over time many people grew to find that node useful for various reasons. I joined the company in 2010 and for years when various members of the team (myself included) would go to events or talk to VB developers we’d consistently get feedback “I wish you’d show the References node”). We were pretty confident on the feedback and that we wanted to unhide it in the next release.

It’s a one- or two-line change but the code that hid the node belonged to another team at the time. That team was responsible for a lot that release including a big part of the story for building Windows 8 apps and I politely asked them to unhide the node to make my customers happy and they politely stonewalled me using every mechanism in the book.

  • They said, “Well, we shouldn’t just change this thing we didn’t know anything about… if only there was feedback”
  • I said, “There was feedback”
  • They said, “Yeah, but if only there were a UserVoice request”
  • I said, “There is a UserVoice request”
  • They said, “Yeah, but does it have votes?”
  • I said, “It does”
  • They said, “Oh, but the vote count isn’t very high”
  • I said, “It’s high for the VB category and we’ve consistently gotten this feedback verbally at conferences for years”

This went back and forth for a while with the goal post moving about. They wanted reports, focus groups, user surveys, UserVoice requests, high vote counts, telemetry, revenue statements and tax receipts from the companies the customers asking worked for. There’s a bit of an adversarial system there for collaboration and the truth is that team was buried in critical work and it was cheaper to burn down my willpower than to have an engineer remove the offending line of code.

A few years later, sometime between 2013 and 2015 the Roslyn team took ownership of the code that caused the references node to be hidden (for unrelated reasons). I went into the office of an old VB IDE team member to find he’d already deleted it. Apparently, it took like 5 minutes. No muss, no fuss, no red tape.

The point of the story is that 5 minutes of real work took 5 YEARS to actually implement not because of any intrinsic complexity or risk to the work or because anybody had malice toward VB.NET users. But because the organizational structure made it very time consuming. Yes, there are mechanisms (escalation) for resolving these disputes but that doesn’t reduce the effort of doing a thing it grossly increases it at a cost of precious political capital and the people who suffered for that (again, sans malice) were the VB customers in those intervening 5 years who couldn’t access that value. Once it reached a state where it could be solved autonomously it was.

I once had a PM argue that VB.NET developers were probably outside of their scenario because “the target for this feature is really large legacy code bases”. (eye roll) It’s not that he was malicious. He was just willing to say anything to defend his team from any more work from anybody. I could tell you other impressively illegitimate pushbacks (like how maybe compiling was outside of the scenario of building projects) but we don’t have time.

I’ve seen features with universal agreement across an org (all teams and managers) still fail to be implemented for years and others implemented only to fail to be checked-in and shipped because of analysis paralysis and a reluctance for anyone to take responsibility or to simply feel empowered to provide that customer value (I originally wrote out those stories but have cut them for pacing).

And on top of that re-orgs, manager changes, and office moves were frequent enough at Microsoft and any of them can reset an entire effort requiring re-discussion, re-validation, and re-approval, and rescheduling. I’ve seen customer value that was only delivered because some courageous principle level developer literally went rogue and “just checked it in”.

Last story (on this topic). For the 2015 release of Visual Studio we’d began with the idea that after a long break without any new features in either language (remember that no new features came in VS2013), we would do what we called “just do it” features. Small, harmless productivity enhancers, many of them long requested from community members, that were low cost so we could get a number of them in the release. And, as had been the case for almost all of the Roslyn project, VB and C# were handled by a single unified team (more on this later). So, here’s what happened: VB design meeting put together a list of great small features. C# design meeting put together a list of great small features. The VB features were fairly low risk (but not necessarily low value) and the C# features started out similarly (some were just analogs) but certain differences in the design philosophy of what was enough or “a little more” or “properly generalized” on the features meant that the C# versions of those features became more complex over time and riskier. So, we (I was on that unified team) tactfully decided to front load the C# features because we could get earlier feedback and uncover more risk and since the VB features were all pretty straightforward, we could circle back to them a little later in the product cycle. But the C# features just kept growing and growing and getting more complex. Then an asteroid hit campus or something and there was an unexpected schedule contraction and now instead of having a year to wrap up we had like 3 months. Ultimately the C# versions of the features grew to such complexity and some of them actually grew out of being useful entirely and most were cut AND almost all of the planned VB features had to be cut and there I was starting VB String Interpolation after officially we were “feature complete” just to ensure VB customers would get any big value that release. To be clear, another team member was writing C# string interpolation in the same timeframe. It wasn’t that C# was in a good place either. Multiplexing the team, combined with the C# natural progression of the design approach had eaten so much of the schedule that when disruption happened it negatively impacted BOTH languages. I’m not complaining about the C# design approach, to be clear. I absolutely get why they design how they design—it creates a consistent language philosophy for C# users. I’m just stating that multiplexing the same team to manage two languages failed hard. Maybe I could have anticipated that, or the inevitable schedule disruption. Maybe I could have been more contentious about it in the beginning or the middle but I shouldn’t have had to be. That same set of circumstances had no real impact on what F# delivered in VS2015.

So, there was a chaotic system and an organizational structure on top of that system that could not react to disruption and the wheels ground to a halt. Whether it’s because of thread starvation or context switching or deadlocking or whatever processing analogy you want to come up with that approach repeatedly failed for reasons completely devoid of malicious intent.

“Well it sounds like there’s some dysfunction. There’s the problem! Shouldn’t Microsoft fix that so that they can get the current model to work for VB too; isn’t that the ideal?”


C# and VB have worked under what I call the distributed model, where there’s some experience scattered across multiple teams. And for C# that generally works for a number of reasons—usually getting C# to work is essential to drafting the infrastructure and design of whole systems and platforms. But there are plenty of times where taking the same approach for VB.NET isn’t needed, doesn’t work, or does more harm than good.

For example, samples and templates. It’s not enough for another team to create a template. The “VB owners” have to review and modify all of those templates with VB specific knowledge. For example:

  • Should this project use VBCore?
  • What should the default project-level imports be for this project type?
  • Do the default items and item templates for this project make use of or work correctly with a project root namespace?
  • Does this project enable or disable the prescribed set of VB recommended warnings?
  • Does this project template correctly exclude an explicit setting for project-level Option directives? This is essential in order to respect each user’s VS wide project default settings which are synced to the cloud: if there’s an explicit setting in the file VS won’t override it with the user’s stated preferences.
  • Are certain items appropriately nested (or not) under the My Project node?
  • Etc.

This list of checks is even larger for samples because there’s usually more code. Some are functional but others are stylistic like:

  • Did the person who wrote this sample use `Object.ReferenceEquals` because C# doesn’t have a reference equality operator and these uses must be now be updated to use VB’s `Is` operator?

For actual functional changes they have to be tested for working with the VB tooling and experience. Even with automated tooling there’s still a manual process that has to take place and it has to be done by people who actually understand VB and its features and how to leverage them best. And it often has to happen multiple times when samples or templates are updated pre-release. No one really benefits from the other team “owning” any of that work (or front-loading it) and just getting a bunch of bugs filed on them. It’s an unknown quantity that they may not have the capacity or capability of completing. And even in the event that that work is prioritized through escalation that creates a culture of tension and adversarial defensive hyper-vigilance rather than collaboration because these ticking time-bomb work items have the potential to seriously disrupt partner teams. It’s not a just a symptom of collaborative dysfunction; it causes collaborative dysfunction.

That’s for external teams but for the C# language this is especially untenable for all involved because C# advances the .NET platform. I’m not begrudging or envying them that role but recognizing that that’s what the language has always done where VB is traditionally focused on innovation in experience. It’s not that you can’t write a library or a framework in VB (and people have) but the .NET platform is not and will never be dependent on the VB language (or F#) to make leaps. But if C# is late developing generics, .NET 2.0 doesn’t ship. If C# hasn’t figured out the shape and behavior of nullable value types those types can’t appear in any new APIs. If it’s late on LINQ, .NET 3.5 doesn’t ship. If async isn’t complete, .NET 4.5 can’t ship with new asynchronous APIs. If C# language design can’t converge on ref returns or nullable annotations the platform teams (like mscorlib) that depend on those features literally cannot ship their platforms for anyone. And for what it’s worth, C# is ALWAYS late on those things (a fact I learned too late) because getting it right takes all the time in the world. Which is why it’s insane (in hindsight) to envision an “ideal” world where you couple or serialize a language which does not fulfill that mission critical role with so many downstream dependencies and its customers’ productivity with one that does and expect good things for both of them.

And no one is trying to move F# to this model.

In the past when Microsoft was more closed source and teams were a lot more possessive about their code maybe this was the only way to do it but the culture has changed there. It’s a lot easier to just submit a PR (even internally) from the team that owns VB and have that team review and sign-off as needed. Things have changed and there’s room to change for the better because of it.

“But a small dedicated team doesn’t scale!”

Is the status quo scaling? Are we tired of scaling yet?

I’ve had the same # of cores in my desktop for the last 8 years; they’ve scaled to everything my computer has done in that time. Nothing didn’t happen because the # of cores was fixed. The current model for VB.NET has literally “scaled” to 0.

Which brings me to…

How did we get here?

In any situation it’s easy to imagine that things have “always been like that” or that they “must be like that for a reason”. There usually are reasons and sometimes those reasons were valid once and are no longer and need to be re-examined. Let me take you on a trip through time…

  • In the beginning (VS2002-VS2008), VB was its own product unit. You could actually buy VB.NET as a standalone product and it had its own budget, staff, marketing team and everything. C#, I believe, started out as a part of the C++ PU until it got big and moved out. Everything that happened in VB.NET up until around 2008 (LINQ) was from the VB PU, and everything in C# from the C# PU. There’s a picture from that time of Anders and like 50-100 people working just on C# (wearing C# T-Shirts) so I guess they had a lot of people and VB had a similar number of people. As many of you will recall, this split led to lots of good stuff but different good stuff and there was some wailing and gnashing of teeth.
  • After VS2008 co-evolution came and VB & C# were merged into a single PU: Visual Studio (Managed) Languages or VSL. Eventually F# and the Dynamic Languages IronRuby and IronPython, were part of this org.
  • When I joined VSL in 2010 here’s what the layout of VB (approximately):
    • VB Compiler Dev: 5+ devs + 1 lead
    • VB Compiler Test: 4+ testers + 1 lead
    • VB IDE Dev: 5+ devs + 1 lead
    • VB IDE Test: 4+ testers + 1 lead
    • VB Compiler PM (Me)
    • VB Language PM (Lucian)
    • VB IDE PM (Dustin)
    • VB Community PM (Beth/Lisa)
    • C# had the same layout so both VB and C# had ~25+ people working on each language them across their IDE and Compiler & 4 full-time PMs each.
    • F# always had a single PM who owned everything and their compiler and IDE teams were merged but they still had dev and test separated out so it was probably a third the size of either VB or C#. Let’s say ~9 people, not including Don Syme.
    • There were a couple extra layers of management for each discipline and each layer but it was a little lopsided.
  • After VS2010 we started working on VS2012 and Roslyn (which we thought would ship in VS2013 but ended up shipping in VS2015) in parallel. The team split with some folk working on VS2012 and some working on Roslyn. A combination of diminished scope and the usual staff reshuffle after a release as people move on to other teams really shrunk down the VB and C# hierarchies a bit. Completely accidentally every “team” on either version was missing one person in either a leadership role or a particular language so we consolidated some for efficiency reasons (at first).
    • The Compiler C# PM/VB Dev Lead/C# Test lead ended up owning both languages and eventually the IDE experience for VS2012.
      • Compiler has maybe 8 devs (at first) and 6 testers.
    • F# stayed pretty much the same, a separate team with one PM working toward its next release in VS2012 but it eventually consolidated its dev lead and test lead roles.
    • The Compiler VB PM/C# Dev Lead/VB Test lead ended up owning both compilers for Roslyn.
    • The IDE VB PM/C# Dev Lead ended up owning the IDE for both languages for Roslyn.
    • There were these cool extra “architect” people on Roslyn.
    • The VB Community PM ended up owning both languages.
    • VB and C# Language PMs remained separate.
    • The VS2012 team decides to do async in both languages and grows significantly.
  • The Roslyn IDE might have set out to be unified across both languages pretty early but the compilers were originally designed differently and implemented separately. That’s what drove unification. Their designs were a little different and we observed strengths and weaknesses and different valuable optimizations that each language had come up with in their compilers or interesting tradeoffs that had been traded in opposite directions. And as we were trying to get the performance of the data structures right, we ended up trying both approaches and hybridizing them and eventually it just made more sense to unify the dev teams (they already shared a single dev lead) to get a consistent uber architecture going forward (there are still some differences but they’re very much intrinsic to the languages).
  • Compiler test was also unified and this was AMAZINGLY valuable because the test team found so many consistency issues with the APIs between the two languages that drove the design to be better and many differences between the actual language semantics that simply drove understanding of the differences between them.
  • Post VS2012
    • The VS2012 team does a little work on VS2013, same structure as in VS2012.
    • F# gets spun out to another org entirely.
  • Post VS2013
    • The VS2013 VB/C# experience team joins the “Roslyn” org.
    • The VS2013 VB/C# experience team DOES NOT join the Roslyn compiler or IDE teams and becomes something else entirely eventually working on .NET Analyzers.
    • Eventually F# rejoins the Roslyn team reforming Managed Languages. At this point they have like 4 engineers total (I think) and no PM (an engineer owned PM tasks). Their numbers shrink and grow and they go through several PMs.
    • Eventually Dev and Test are unified across the entire company. For multiple reasons, by this point the unified engineering team (which owns both dev and test functions) is maxed out at maybe 10 non-managers. This is less than the combined size of dev and test before.
    • Somewhere in this dedicated community PMs disappear. VB language PM takes over community for both languages.
  • Post VS2015
    • I own … VB & C# compiler, debugging (EnC, EEs), eventually language, Analyzers, the Roslyn compiler APIs, scripting, interactive (REPL), part of .NET native, part of VSCode, debugging again, analyzers again, and some set of community engagement (not always all of this at once).
    • Mads is the C# language PM still, owns a piece of community.
    • F# has a PM again.
    • There was an IDE PM and then there wasn’t technically and then there was but it was a different view of the IDE
    • Part of the IDE also split off to own something else.
    • The “Compiler” team which was the doubly unified VB and C# engineer (dev and test) team (still ~8-11 people) also began to take over some bits of what the IDE team used to do while the IDE team was taking over everything else in creation.
    • Oh, we open sourced everything and that added to what had to be done across the board.

The point of this very long outline is that no divine being ever said “VB and C# ought to be organized this way because it’s good and right and true and best and it would be immoral to organize them differently”. Consolidations mostly just happened in reaction to needs and limitations in the moment and persisted due to inertia. At specific times and in specific areas there was value in the organization but by late in the VS2015 cycle it wasn’t working anymore but we didn’t seriously question it (even me—I thought it was a one-off; I was wrong).

Further, there were like 30 reorganizations and changes to company culture and management at every single level of the hierarchy and across multiple disciplines over this time period with each new manager inheriting this structure from the last probably thinking “That’s how they’re organized because that’s the way they figured they should be”. It’s a historical artifact and nothing more. If it isn’t working anymore (and it hasn’t been) then that structure should have been dumped long ago for something that works.

Meanwhile F# continued to be an autonomous team also mostly because of inertia. They may have reported up through the same managers as the VB/C# compiler team (sometimes) or IDE team (other times) but they remained separate functionally (no pun intended) which meant that no amount of stress on C# specifically could impact F# at all.

“It’s a zero-sum game. Divesting in VB would make C# happen twice as fast!”

This is demonstrably untrue for several reasons. You can certainly organize them in a way that forces them to be a zero-sum game but it’s not essentially the case.

The first reason is…


It’s not the case that if you have a developer (or other role) that works on one (or two) languages that they can just slide, or more importantly be slid over to another language. I’ve seen this attempted many many times between VB, C#, Python, Ruby, JavaScript, F# in various combinations and in both directions. More often than not that person just leaves the team or the company. It’s not a win for the company because that person isn’t simply replaced with an equally good but more fungible person because HUMAN BEINGS ARE NOT FUNGIBLE RESOURCES. That idea is fantasy. On rare occasion it works but overall, the broader organization just gets smaller and weaker for it because you lose that person’s uniqueness.

The second reason this isn’t true might shock you…

There is a maximum effective team size for any language/layer/component. If you look back at my outline of the history of the team structure, you’ll note that after VS2013 we (the Roslyn VB & C# compiler team) didn’t just absorb the members of the VS2013 VB & C# compiler team. I remember discussing it and the feeling was “the team’s already large enough!”. Even though we had massive scope for where we were in the project adding more people wouldn’t have double the speed or anything and would have slowed things down. Teams grow in scope, not in size. You can get more people by creating a more complex hierarchy but that complexity also reduces efficiency.

And as a personal example, sometime around the middle of 2016 I sincerely tried to leave the PM discipline to become an engineer. There were big changes going on in the PM org. I was in the beginnings of my current nervous breakdown. My depression was spiking. I was super unhappy where I was, I said as much, and I tried to move over to the team that most aligned with my skillset and knowledge to try to manage my stress. I talked to engineering management and I asked several of the Principal-level engineers on the compiler team, with whom I’d worked at that point for 6 years and who had by that point seen many of my check-ins to sign-off on it. All of them were comfortable with me joining the engineering team but I was told by management that the compiler team (then at 10 or 11) was simply too big. The goal for team size is like 6-8. It could not take another person until it attrited 2-3 people and that was it.  

My point is, there is a MAXIMUM number of people who can work on the C# compiler effectively and efficiently. Not having people assigned to VB or F# just means having fewer people assigned to those languages and/or fewer people working at Microsoft, it does not produce any automatic boost to the speed at which C# language features can be delivered. If that weren’t the case Microsoft could just hire 50 more compiler majors from Waterloo and everything would be golden. If you want to put 3 people on VB you don’t take them from C# compiler you just add space for 3 new people to the org and fill those positions. Multiple times has someone tried to force people to work on one language or another and they’ve usually failed, and multiple times has the team responsible for the C# compiler rejected new engineers on account of team size. So, this idea that anything has to be done to VB to protect the velocity of the C# language isn’t borne out by the history.

And forcing one team to own scope that was previously owned by 5 teams: [(compiler + ide) * (dev + test) + PM] or even two separate product units is precisely what creates an artificial zero-sum game.

And just importantly, not having a distinct VB team means…

Accountability is impossible

When I came back to Chicago in 2018, I had a huge issue with getting gigabit internet in my apartment. I was extremely angry with Comcast and to this day have not pursued their gigabit internet. I almost took to Twitter I was so mad. But through my incalculable rage I tried to find some productive understanding of what took place and I realized that I was, or at least shouldn’t be enraged with their customer service department. They couldn’t call up the service tech who never showed up. Days later they couldn’t find out if he ever showed up for work again or if he’d had a heart attack in his truck. They couldn’t prioritize sending out a new tech sooner than 2-3 weeks out. They couldn’t waive the requirement for a tech to do the installation to allow me to attempt a self-install. They couldn’t escalate to call in an unscheduled tech for overtime to correct their mistake. All things they should be empowered to do but they couldn’t actually do. And I was mad because I didn’t know that and human beings expect that when they reach out to other human beings for help that those other human beings will visibly try. But they were disempowered customer service. And it caused massive negative sentiment from me toward their customer service and this non-living corporate entity. But I realized my issue wasn’t with the customer service but the organizational decisions which put those people in the position of being disempowered but ostensibly accountable.

A VB.NET community member reached out to me early last year and, frustrated, asked “Why can’t … just say ‘the plan is to do x’ or ‘we’re working on y’ but they can only say this vague aspirational statement?”. They were furious. But when almost every experience, every value-add that you want to provide to your community is distributed across 2 or more teams none of which is a dedicated VB.NET team, you can’t actually be accountable to the community. You can’t have plans. You can’t have roadmaps. You can’t have schedules. You can’t truthfully state that “you’re” working on it or towards it because 3 or 4 nodes in the system have it on a list but you don’t have the influence and specifically the authority to predict the outcome. You don’t have the agility to make adjustments based on feedback on functionality or priorities. You just put inputs into the system and have to hope that the answer that comes out in a few months’ time is one that pleases the community. And if there’s enough stress on the system nothing happens. Everyone team involved gets veto power or every partner team has a management hierarchy which has their own conflicting priorities or their director who needs to sign off on it is out on vacation this week or they just left and we’re waiting for the new person or they need to align with their bosses commitments that just came in or “we’re buried right now because BUILD is coming up” or “Ignite is coming up” or “VS1X.Y update is coming in hot” and these things are always coming up.

And because no one owns the work, no one can rightly account for it to the community. No one can own the story or the message on it because no one controls the story. There’s no story to own. It’s similar to that old saying about parallelism, 9 women can’t have a baby in 1 month. You can’t just average “20% focus on VB.NET” over an organization of hundreds and expect to get much. Except problems.

A few examples:

Some VB developers wanted to use Azure Functions and there weren’t any Azure Function templates in the box so some VB MVP stepped up and made a template. Sounds like a win for VB, Azure, and open source, right? But the process breaks down because the Functions team rightly asks: “Who’s on the hook for maintaining this template moving forward? What if it needs to be changed? What if these static text files that never change need to be converted into a right-to-left YAML format!? We don’t have budget on the schedule!”. So, I say, fine: let’s create a templates repo for community templates similar to what F# has done. But now the question is “Who’s on the hook for maintaining and operating this repo?”. An open source contribution and a sustainable model for open templating going forward dies in committee. And there have been other templates and open source contributions who died similarly.

A developer wants to contribute code to VB.NET: “Who has the time to review his PR, to give him feedback, to work with him to fix the feedback! No time!”. Dies in committee.

We had translated and reviewed samples for Windows 10/UWP ready: “Who’s on the hook for maintaining these 140 samples!? They’re likely going to change and we can’t absorb those costs”. UWP samples die in committee.

The community has repeatedly expressed interest in mobile development using Xamarin. I understand the desire and that the Xamarin team, newly integrated into Microsoft, is doing a lot of stuff. The work for Xamarin.Forms support is not “nothing” but it’s also not insane (it’s mostly just a code generator). So, the Xamarin team kindly offers us access to their repo to simply investigate getting it working (similar to what was done for WP7). But without a dev to start the work and MORE importantly a team that can commit to potentially owning any bug tail or ongoing support costs for that component however small they’re expected to be that very reasonable approach to solving a community pain point can’t move forward even if a tactical strike is possible in the short-term.  And no one can fully account for that breakdown.

Ignoring whether that’s actually the best solution for VB developers wanting to explore mobile development, the problem is that no one can rightfully account for that investigation even happening: “Sorry, we decided … well, didn’t decide, but couldn’t do the thing no one could actually committed to doing because there was no one to commit to it in the first place so we couldn’t tell you about it beforehand so now I’m letting you know it didn’t happen because there was no logistical reason for it to happen or way of knowing if it was even possible to begin with. This sentence does not exist.”

And I could cite example after example of language features, tooling features, platform features, open source contributions, samples, templates which aren’t expensive in raw engineering effort but are prohibitively expensive due to the bureaucratic gymnastics necessitated by the lack of an empowered, dedicated, small, agile VB.NET team accountable to the community. And that is how we get where we are today. Not cost. Not practicality. Not philosophy. Not necessity. But failure to adapt. Neglect. Which doesn’t require conspiratorial malice; but that doesn’t matter because at a certain point—the point we’re at right now—any sufficiently advanced negligence is indistinguishable from malice.

In Conclusion

As I said in the beginning, this is not a reaction post or a response to a particular event. It’s something I’ve been working on for a while now in response to a progression. I am posting it now so that as conversations take place about where we are, everyone understands that the current situation is entirely and easily avoidable. If you’re not a VB.NET developer who’s just curious or observing this, understand that nothing reasonable is forcing these negative outcomes. It doesn’t take an army or millions of dollars; it just takes Microsoft getting out of its own way. If you’re a VB.NET community member, know that a better, sustainable, proven alternative is possible and do not be distracted by the addition or absence or promise or request for any particular feature, large or small, any template, any sample, or concession of support. The F# community, a much smaller community than that of VB.NET has (and has always had) a dedicated team working and advocating on their behalf throughout the .NET ecosystem as their main jobtheir first priority—every day. There is no reason that after 18 years of loyalty, the VB.NET community doesn’t deserve at least that much. Focus your intentions on this goal because regardless of what anyone says the support of a small 3-5 person, agile, empowered, autonomous, passionate, and dedicated VB.NET Team, separate from C#, is the only support that means anything.

-Anthony D. Green

Pattern-based XML Literals Prototype: Client-Side VB.NET Running in the Browser (sorta)

At last, the final video in this series on pattern-based XML literals. That culmination of all my machinations! Last time I showed you all some example web controls—classes that know how to render their behavior using the standard web primitives of HTML, CSS, and JavaScript. The next logical conclusion is knowing how to render VB.NET itself to JavaScript. Check out this video as I run through three examples.

This isn’t anything radical (outside of the common use of the word meaning cool, in which case yes, it is!). This is the same technique developers all over the world use every day with LINQ and Entity Framework. Leveraging expression trees to write code in VB.NET that is then transformed into SQL and executed on another machine. I’m using those same capabilities to let me write glue code with the same convenience.

And to be clear, this is the exact same pattern I used for my Xamarin post last month. I haven’t changed it to support this new use. It’s just sufficiently flexible that it could enable this “out of the box”, so to speak. You see, because the XML pattern can instance and initialize arbitrary types, when those types make use of other types like System.Linq.Expressions.Expression that rich information is available to the compiler so things like the natural ability to convert to lambdas to expression trees just “falls out”, as we say.

An interesting bit of trivia: Originally, I did plan on (and I am proposing) extending the currently limited set of language constructs supported by expression tree conversion. However, I did not have to extend it nearly as much as planned. 1) Statement (Sub -> Action) lambdas are already convertible to expression trees in a very few cases, 2) I was surprised to learn that assignment is one of those cases if and only if the target of the assignment is a property. I’ll add that to “The List”. So, for this demo I just relaxed the restriction that syntactically the lambda had to be a single line lambda just to further clarify for viewers that this is an assignment, not a comparison. But even without that, the ingredients are all there.

The product of the whole is much greater than the sum of the parts

This is the power of orthogonality in language design. Every feature doesn’t have to be “big” if a number of smaller seemingly less sensational features can work together to produce a great result.

  • Top-level code has been independently requested throughout the years; it’s not a “big” feature to design or implement nor a massively disruptive addition to the language.
  • XML literals were added to the language over ten years ago with a narrow focus on providing a declarative syntax for using the XLinq API; it’s not a radical suggestion to generalize this useful albeit niche feature to bring that declarative productivity to other types.
  • Expression trees have also been around for a decade and members of the community have independently suggested extending the languages to support more of constructs on multiple occasions throughout the years.  

Each of these is a mere evolutionary step of 10, rather than a revolution step of 100 but 10 x 10 x 10 is 1,000! And if you think about adding JSON literals to the mix there might be even greater rewards!

What’s next?

Somewhere out there in the VB web development community is the author or authors of the next built-for-VB web framework a la DotNetNuke (originally written in VB.NET) or Suave (built for F#). My question to those community members is:

  • If you had a language with the richness of capabilities and tooling like VB.NET—things like Async/Await, string interpolation, and LINQ
  • And that language was homoiconic—you could easily get a data structure representing the code written in that language to manipulate and even translate as you see fit
  • And that language could natively describe the two most important data structures on the modern web, the DOM (via XML literals) and JSON (via JSON literals)
  • What could you do with that?

I’m personally very excited to find out!


For a few years now I’ve been wrestling with the growing complexity of modern development. It’s pretty obvious that on top of HTML, CSS, often SQL, sometimes RegEx, managing two general purpose imperative programming languages on the client and server respectively is less than ideal. JavaScript developers who want to use JavaScript on the client and server can use Node.js. VB.NET developers who want to use VB.NET on the client and server need a solution. For me it’s a big productivity boost. But for a new VB.NET developer deciding whether to start prototyping their idea in WinForms where the just have to learn one language or the web where they have to learn 3 languages, 4 frameworks, 2 package managers, … you can see why a lot of people start in WinForms even now. I love WinForms, I want to love web development too! Pattern-based XML literals will be a powerful first step in reigning in some of the complexity and I hope this post/video gave you a glimpse into how.

I’m certain I’ll probably do a one-off post showing more on this topic in the future but this wraps up the series about this prototype. I’ll decompress my design notes on GitHub ASAP and post an update on this blog when that’s done. I absolutely want to discuss a whole bunch of interesting design questions about a hypothetical VB.NET web app framework built using the techniques I’ve shown in these last two posts, but I want to be clear that that effort is orthogonal to this feature. To that end I’ll decompress a separate set of thoughts about it specifically in the post after my next one.

Until then, as always, thanks for reading, thanks for watching, please share this post, and let me know your thoughts in the comments below and/or on Twitter.



P.S. I really wanted to post this back to back with my last post but due to several surprised visits, I’ve had out of town house guests every week of this month. As much as I wanted to be a terrible host and neglect my friends and family to tweak my expression tree -> JavaScript visitors I failed to do so. Yesterday and today I was finally able to carve out a little time to record, edit, and upload the video and this post before even more out of town visitors arrive. Special thanks to my younger sister who is patiently waiting in another room for me to hit Publish so we can go get some breakfast.

Pattern-Based XML Literals Prototype: ASP.NET Core Revisited

This is my third post in this series about pattern-based XML literals. In my last post I showed how you could apply the concept to the Xamarin.Forms library via extension methods to build a cross-platform mobile app in VB using what are essentially “XAML literals” to describe your UI. In this post I’m revisiting the web and showing how someone could use the exact same pattern to not only make a dynamic ASP.NET Core MVC app but how to do so while reducing code by 50-80% using one classic idea!:

Yep, web controls. I know. But these aren’t like the ASP.NET WebForms web controls. There’s no view state or post-backs here; it’s still all MVC. These controls just know how to render themselves and that counts for a lot!. And, as I said earlier, this is the same XML-pattern at the language level that I used in my Xamarin video, the only thing that’s changed is the types that are being constructed (and they were built with the pattern in mind so no need for extension methods). Also, I temporarily merged in my top-level code prototype to get back that sweet full-file top-level XML expression experience! I didn’t change the pattern any, which is a good sign.

My personal rematch with an old challenge from the early 2000s…

From September 1999 to June 2003, I was in high school (I’m currently 34 for those of you doing the math). I was in our high school computer club, tasked with building what was then our high school website. I wanted to liven up the site with “DHTML” (i.e. JavaScript) that would create a drop-down menu instead of requiring navigating the site through clicking through a tree of links. I thought I was soo cool.

I got some examples off of some website, (it might have actually been called or something) but the menu was soo tedious to implement. I vaguely recall making a VB6 app that would generate the menu from an indented text file, it was that tedious. Compare my high school experiences with this declarative masterpiece:

And all I had to do was spend the next 7 years coding, get a job at Microsoft on the programming languages team, design programming languages and build compilers for 8 more years, and voila! It’s so simple!

Full comparison of source code and HTML output here.

A Declarative and Object-Oriented Approach

Even just using plain HTML/CSS/JavaScript, it’s gotten better (and I’ve gotten better) but the web can still be pretty tedious compared to what I’m used to and love about traditional desktop app programming. Sure, HTML is declarative but depending on what you have to declare one person’s declarative is another person’s spaghetti-code and generating certain common, exciting, interactive web experiences can easily liter you page with tons of implementation details.

Encapsulation FTW

Pattern-based XML literals let me use my object-oriented instincts of abstraction and encapsulation in a crazy-productive declarative way. And I actually experienced one of the benefits of this encapsulation immediately first hand. While writing the carousel example I started from the ASP.NET Core sample but later moved to the w3schools example because one of their pictures was named “Chicago.jpg”. Little did I realize that the W3Schools was using Bootstrap 4 while the ASP.NET Core sample I had started with was using Bootstrap 3. Well, in between 3 and 4 Bootstrap changed a few things (understandably):

  1. The CSS classes for carousel items went from class=”item” to class=”carousel-item”
  2. The CSS classes for carousel controls went from left carousel-control to carousel-control-prev
  3. The glyphicon library that had previously been included by bootstrap no longer was so the carousel controls which used it no longer rendered correctly.

In short, nothing worked. Had I been directly using this carousel code (or some other element) across a real site, at that point I’d have to manually go through all of my pages looking for divs with class “item” and manually update them—for EACH ITEM. Once I realized what was going on, I just updated my Carousel control class once to generate different output for items and I was done. Next run of the app the page rendered correctly without having to change any of the markup in my Index.vb file.


Controls are perhaps the most empowering abstraction to ever touch my life. Entire ecosystems of control creators and vendors sustained the VB community for decades. And a world where there aren’t re-usable control components to hide and handle basic rich UI experiences is an incredibly complex one that I’m not particularly interested in coding in.

Reducing complexity through abstraction, encapsulation, and polymorphism is a very object-oriented approach to the web. But to be able to use them it helps to have “objects all the way down” and traditionally that would mean giving up the declarative simplicity of markup languages like (X)HTML. With pattern-based XML literals that doesn’t have to be the case. This potential feature massively scales up the expressivity of the XML literal-based ASP.NET Core view engine I showed back in May and opens the door for even more cool stuff I’ll show in my next post.

I do want to talk about the idea of what a real (not made for demo purposes) web controls library would look like but that’s a separate conversation from discussing this prototype so I’ll be giving that topic its own post as well.

Until then, as always, thanks for reading, thanks for watching! Please share this post, and let me know your thoughts in the comments below and/or on Twitter.



P.S. As in my last series, I’ll upload all of my notes from implementing the prototype in a GitHub issue after the last post in the series. Don’t sweat the specifics of the pattern too much, they’re subject to and very likely to change. This post took me much longer than usual because I had to take a refresher course on CSS, JavaScript, the DOM, and write an entire naive implementation of a self-rendering class hierarchy modeling all the HTML elements used in that video (don’t worry, inheritance took care of a lot of the work).

Credits to these sources for their help:

  • W3Schools – Expander, Menu, Carousel examples. This site is an indispensable resource to all things web.
  • HTMLDog – Multi-level Menu example.
  • Jason Chatonda – Sound editing, because this video had a lot of esses in it. Imagine Daffy Duck soliloquizing on the superior splendiferousness of XML, expanders, menus, carousel scripts and CSS specificity.

Pattern-Based XML Literals Prototype: Cross-Platform Mobile Apps w/ Xamarin.Forms

In my last post I introduced the idea of pattern-based XML literals—XML literals which construct arbitrary types other than XDocument/XElement/XAttribute/etc. And as promised, I have recorded a video showing off the practical benefits of this design when using Xamarin.Forms from VB.NET. If you’re not familiar with Xamarin.Forms it’s an API that abstracts over the differences between mobile platforms like Android and iOS to make it easier to create and maintain cross-platform apps while sharing the maximum amount of code. Watch as I explore the Xamarin VB sample app from the official Xamarin samples repo using this new prototype:

As you can see, it’s pretty empowering to be able to use XAML everywhere.

  • I can leverage my XAML skills from WPF to a degree and be more productive.
  • If I’m looking at the documentation or a sample or blog post (most likely written from a C# developer) that uses XAML, I can use that XAML in my code rather than first translating it to VB imperative code.
  • In places where today you’d possibly have to give up markup for code like dynamic view creation, I can still use declarative XAML even if it’s in the middle of a VB method (this scenario comes up in writing VS extensions to the WPF editor too).
  • Even with object initializers there can be situations where you have to fallback to imperative syntax like using attached properties but that’s not an issue using markup.
  • I get to embed any VB expression inside my markup in places where that expressiveness is a benefit over XAML.

WPF XAML vs Xamarin XAML

Xamarin has its own flavor of XAML. It’s essentially the same on the surface (syntactically) as what’s used in WPF and Silverlight (and UWP) but it’s not the same XAML engine and it uses different types internally. Not just in the “Controls” or as Xamarin calls them “Views” but in the infrastructure itself:

  • So rather than DependencyObject and DependencyProperty, Xamarin has BindableObject and BindableProperty.
  • Xamarin has its own base types for type converters, and markup extensions, etc.

So, even though both it and WPF use the XAML syntax (which is XML based), Xamarin.Forms is powered by a completely different engine entirely. Possibly as a consequence of this the XAML used by Xamarin.Forms doesn’t support VB.NET. Which would normally mean you have to create your UI imperatively, rather than declaratively. VB guru Klaus Löffelmann wrote about how to do this back in 2017 on the VB team blog. It was a good post but the no-XAML part was kind of a bummer. This prototype changes all of that!

The Xamarin differences actually highlight another benefit to being pattern-based. Because the language understands patterns—certain methods with certain names and shapes existing—rather than specific types (like DependencyObject) it’s possible to apply the feature to a completely different system than WPF. If the feature were just WPF XAML literals built to understand the specifics of the WPF infrastructure you couldn’t turn around and apply it to Xamarin but by being pattern-based you can do that easily.

Under the hood

As I indicate in the video, the compiler knows XML and how to translate certain idioms in XML into call-outs to extension methods that encapsulate all of the Xamarin-specific knowledge. I’m pretty sure the pattern will change as I explore more but the first page’s code:

Dim page = <ContentPage Title="My First Android App!" BindingContext=<%= Model %>>
<StackLayout VerticalOptions="Center">
Text="Welcome to Xamarin.Forms with Visual Basic .NET!"
<Entry Text="{Binding Name}"/>
<Button Text="Next" Clicked="NextButton_Click"/>

Translates to this:

' Passing `Nothing` as the first arg of Set<AttributeName> methods indicates
' that the compiler couldn't convert the attribute text to the indicated type
' at compile time. If I had written `FontSize="16"`, that line would read:
' `temp1_1_1.SetFontSize(16.0, "16.0", Nothing)`
' The third argument is the value produced by an embedded expression, if it
' doesn't naturally convert to the first arg type at compile time. If I had
' written `Text=<%= New Binding("Name") %>`, that line would read:
' `temp1_1_2.SetText(Nothing, Nothing, New Binding("Name"))`
Dim temp1 = New ContentPage
temp1.Title = "My First Android App!"
temp1.BindingContext = Model
Dim temp1_1 = New StackLayout
temp1_1.SetVerticalOptions(Nothing, "Center", Nothing)
Dim temp1_1_1 = New Label
temp1_1_1.HorizontalTextAlignment = TextAlignment.Center
temp1_1_1.SetFontSize(Nothing, "Medium", Nothing)
temp1_1_1.Text = "Welcome to Xamarin.Forms with Visual Basic .NET!"
Dim temp1_1_2 = New Entry
temp1_1_2.SetText(Nothing, "{Binding Name}", Nothing)
Dim temp1_1_3 = New Button
temp1_1_3.Text = "Next"
AddHandler temp1_1_3.Clicked, AddressOf NextButton_Click
Dim page = temp1

As you can see, the compiler knows how to translate attribute values to enum members at compile-time. So if I misspell and enum member I’ll get a compile-time error:

Likewise the compiler knows how to translate an attribute value to a delegate creation, so that too gets compile-time validation:

Both of these make it easy to give in-context completion support in the IDE for these cases.

The keen observer may have also noticed that when I selected name CalculateButton in the value of the Name attribute at around the 2:45 mark in the video that references to CalculateButton in code were highlighted. This is another example of the power of Roslyn. Because the compiler binds that text to the CalculateButton variable, the IDE understands it as such and features like Go-to-Definition work automatically!


I accidentally edited out the part where I show what turns a regular XML literal into a pattern based one and it’s a magic "clr-namespace:" XML namespace import at the top of each file (could also be in a project-level import). If I comment out that import you can see that I get conversion errors because the XML reverts to producing an XElement as it does today:

I expect to find a better way to enable the feature though because of some trade-offs with that approach. This is just a draft version of the pattern and I fully expect it to change as I explore other shapes of XML to apply it to and weigh certain experiences that could be built.

For example, right now the pattern respects both a SetChildContent and AddChildContent bridge methods so that the compiler can report an error if you include more than one child element in a situation where only one child is allowed, but maybe it’s better to simplify the pattern and enforce things like that in a Roslyn Analyzer (let me know what you think).

If you’re really curious as to what each of these bridge methods looks like, I’ve uploaded the content of the XmlExtensions.vb file from the sample app I showed in the video as a Gist. It’s just what I wrote out while exploring the pattern and shouldn’t be taken as the “best way” to write such methods and I played around with different approaches. Just take it all with a grain of salt.

Next steps

I know Xamarin.Forms has been around for quite awhile now but honestly I haven’t been as excited to try it out until now. I can see some places where the Xamarin team made extremely reasonable choices in their content model (like how templating works). I’m anxious to see how I can broaden the pattern to work well with those patterns and to just generally explore mobile app development from VB.NET.

Fun Fact: Due to Windows Mobile and Compact Framework and then Windows Phone and Windows 10 Mobile, I have not owned a phone that I couldn’t program in VB.NET in almost 15 years. I’m excited to continue that tradition.

One thing this video didn’t show off was tooling. Because it’s all just the VB.NET language and the IDE is powered by Roslyn, getting things like completion, go-to-definition, F1 help, etc. to work in such XML literals is much easier than it would have been pre-VS2015. Also, there’s this other unrelated prototype I plan to show off… 4-5 prototypes from now that could really improve on both desktop apps using WPF/WinForms and mobile apps using Xamarin too. So whether it’s to show off better tooling, to show off another prototype, or just because I’m having fun exploring Xamarin.Forms I don’t think this will be the last video I make featuring this topic.

As for my next post it’ll be a continuation of this series about this prototype but instead applied to web development. I think you’re going to love it so look out for it.

Until then, as always, thanks for reading, thanks for watching, please share this post, and let me know your thoughts in the comments below and/or on Twitter.



P.S. As in my last series, I’ll upload all of my notes from implementing the prototype in a GitHub issue after the last post in the series. Don’t sweat the specifics of the pattern too much, they’re subject to and very likely to change. This post took me much longer than intended before the first few iterations of the video were over 30-minutes! It took some re-recording and aggressive editing to get it down to 5.X minutes, but I think that’s optimal for online viewing and sharing. I hope you agree!

“I have made this [letter] longer than usual because I have not had time to make it shorter.”
-Blaise Pascal

Pattern-Based XML Literals Prototype: Introduction

Hey all!

I’ve been down in the laboratory since my last post and I’m back with a brand-new prototype. I was working on scripting the first video for this prototype when I realized there’s just a lot of context to set beforehand so I’m taking a break to write a quick introduction.

What do I mean by pattern-based?

When I describe a language feature as “pattern-based” I mean that the feature is designed to work with any code that fits some pattern the compiler knows about rather than a specific limited predefined set of types. Not every feature is pattern based in VB.NET but several of them are. For example:

`For Each` doesn’t require a type implement `IEnumerable` (or that `IEnumerable` even exist) but rather that it meets the Collection pattern. A type is a Collection Type from the perspective of the compiler/language if it has an accessible `GetEnumerator` method that returns a type with a Boolean returning `MoveNext` method and a readable `Current` property and the `Current` property determines the type of the elements of the `For Each`. None of this requires `IEnumerable`, that’s just convenient and it means that library authors can write specialized enumerators which are more efficient in some way, usually by being structures rather than classes.

`Await` is another example. Everyone knows you can await `Task` and `Task(Of T)` but the language doesn’t require that, rather that the type have a `GetAwaiter` method that returns some type with the right set of members on it. If the type meets that pattern it is considered Awaitable. An example of this in action is the `Task.Yield` method which returns a `YieldAwaitable` structure, rather than `Task`.

Query comprehensions (the SQL-like LINQ syntax) aren’t tied to `IEnumerable` or even the `System.Linq.Enumerable` type either, but rather work on Queryable types—types which have a `Select` method that take a delegate that itself takes 1 parameter, the type of which is the element type of the `From` operator and may have other operators like `Where`, etc.

A big win from the pattern approach is that often a type can be made to support a pattern after the fact through an extension method. This is great when you don’t control the library that type is defined in but still want it to work well with new features. C# and F# also use this approach at times to varying degrees (F# turns it up to 11, actually). There are other features that use patterns (and ones that don’t) those are some big examples. Eric Lippert (of course) talked about some examples on his blog and one of the ones that don’t in either VB or C# (occasionally to my chagrin), the `Using` block.


Right now, XML Literals are in the ones that don’t bucket and I’m looking at what possibilities open up if that changes. These first three scenarios are minor. I definitely thought about them but I understand if they’re not top of mind of a lot of other people. They were stops along the train of thought. The last two though are pretty major so feel free to skip ahead if you aren’t interested in trivia.

Minor Scenarios

Windows Runtime/UWP XML

One of the first concrete scenarios I had was back when I was exploring the Windows Runtime/UWP library and I noticed that WinRT defines its own `Windows.Data.Xml.Dom` namespace which is, of course, not the `System.Xml.Linq` namespace that VB XML literals work with and I got to thinking, wouldn’t it be nice if VB could work natively with the WinRT types. If you look at the docs for creating live tiles and sending tile updates, the whole tile template system in Windows 8.x/10 is built on XML and their code examples look like they would benefit from XML literals and XML axis properties.

That’s one idea. It’s good language hygiene but fairly limited.

Rich WPF Message Boxes

I’m a big fan of Alan Cooper “Father of Visual Basic” (big surprise) and specifically his books on user experience like “The Inmates Are Running the Asylum” and “About Face: The Essentials of Interaction Design”. In one of those books he talks about message boxes and points out the ways software provides poorer, less situationally appropriate experiences because the default APIs are “good enough” and programmers just try to squeeze whatever problem they have into what the API provides rather than writing a custom dialog. It’s been years but I recall him showing an example of some program that wants the user to do one of two things and it puts up a dialog box that says something like “How would you like to proceed? Click ‘OK’ to file your taxes jointly or ‘Cancel’ to file separately with a 1099c extension”. Obviously, this choice shouldn’t be in terms of ‘OK’ and ‘Cancel’ but the programmer was too lazy to write the custom one-off dialog. The programmer has delegated mapping concepts from user-domain to the API to the user and that sucks.

The MessageBox.Show in WinForms and the other one in WPF are a little bit more customizable than this but sometimes I call MessageBox.Show and think “I wish I could provide a formatted string as the dialog text, maybe include some bolding or color or an image but the API just takes a string”. Ideally I’d be able to use all of WPF’s TextBlock primitives and just hand that to a generic built-in dialog presenter. I could write one, of course but there’s still some tedium to it because in my code I can’t use XAML, I have to imperatively construct a potentially elaborate object graph and that stinks.

XML-based DSL’s

If you look at the unit tests in the Roslyn source code, you’ll see thousands of examples of things like this:

An actual VB compiler semantic unit test from the Roslyn code base
An actual C# IDE unit test written in VB, presumably to take advantage of those sweet sweet XML literals

The test team created these DSLs for setting up tests for the compiler and the IDE that other code then parses to create the actual test environment. XML has just enough structure vs strings while being flexible around multiline content. It’s neat and in a lot of places convenient to use XML to describe these test cases declaratively but it’s unfortunate that everything that happens in the XML literal is opaque to the compiler so you don’t get any tooling assistance at compile time. You could help this a little with analyzers but there are still seams in the experience.

Major scenarios


In an earlier post I showed you how one could use XML literals to make a basic view engine for ASP.NET Core. It was nice but because it’s just producing an anemic XML DOM there are some limitations on how kick-ass it could be. I’m trying to see how far I can take it.


On the other side of the spectrum we have Xamarin.Forms. I’ve been interested in Xamarin for a few years now but one thing that bugs me is that to use it in VB I have to use code to construct my UI. I can’t use my XAML skills (until now).

So, I made a prototype…

The challenge is, can I come up with some reasonable pattern that would enable an XML literal to construct and/or interact with things other than the XLinq API. I’ve got a first-draft and some notes and a about 2-3 scenarios to show you based on what I came up with that I hope you’ll like. The first one up is the Xamarin scenario and it’ll be the subject of my very next post. I just wanted to get all the background out of the way so I can focus the video and the blog post on the scenario itself rather than general context setting.



Top-Level Code Prototype: Scenario E

At last we’ve come to the last of my planned scenarios for this prototype–a little thing I like to think of as a WYSIWYG Web Service, or WYSIWYGWS for short. A few months back I had recently finished the JSON literals post and video and was anxiously combing my immediate vicinity for more scenarios when Scott Hanselman came along quite serendipitously with his post, Converting an Excel Worksheet into a JSON document with C# and .NET Core and ExcelDataReader to inspired me.

I asked myself “How simple can defining a REST endpoint be?” and here is the result.

Of course there are myriad ways to approach this problem with various trade-offs, this is just one.

One developer on Twitter asked Scott (paraphrasing) “Why not just use PowerShell?”

To which Scott replies, “Very useful, yes, but would require additional PowerShell to get the output JSON I wanted”

And another developer says, what are the benefits of using ExcelDataReader over this PowerShell command?

And Scott reiterates, “Control over the result is all”

And that’s one key aspect to this scenario. Scott had an idea of what shape he wanted at the end and it was just a matter of getting what he had into that shape. And in the video above that’s exactly how I approach the problem as well, I start with that shape and then populate it. Now that’s what I call… Design by Contract! (ba dum chhh)

Another element to the scenario is data that is… uncooperative:

  • You can’t control it
  • You can’t annotate it serialization attributes
  • The shape isn’t right for default serialization
  • It’s coming directly from an external (not .NET objects) data source like a database, mainframe, device, other service, or in this case a file

And that last point is more important than you might think. Every day (on Facebook) I see a lot of developers working on apps that use DataSets as their data layer and/or are using an RDBMS that doesn’t have SQL Server’s fancy `FOR JSON` clause. Without getting into a big argument about whether those folk need to “Get with the times” and “Move everything over to X”, what’s the fastest way for them to Cloud- or Mobile-enable that data? And even if you do have POCOs for your domain-objects, there are a lot of reports in life and not every report deserves its own custom EndOfYearSalesByRegionReportRecordRow class just so you can use JSON serialization.

It’s also just a useful way and crazy easy way to mock up an service end-point. When I was exploring the GitHub Gist API I was very conscious of how my debugging might look to the GitHub service. Was I hitting the live API up too much? Will I hit a request limit? With this I can just go to a service, grab the output, and paste it and develop against that until I’m ready to hit the live service. Ease in testing is its own reward.


In my last post I combined top-level expressions with XML literals to create a basic VB.NET view engine for web pages on ASP.NET Core. In this post I took the same strategy but swapped out XML for JSON literals to make ASP.NET Core REST services a breeze in VB.NET. The approach has trade-offs and shines especially when dealing with one-off data sources such as files, database reports, and objects you can’t modify for serialization but yet still need to end up in a particular shape in the end, as well as testing.

So what about you?

Do you have any data you need to get out of some less that reputable places as painlessly as possible?

See, the Millennium Falcon in this metaphor is the JSON. Or maybe the JSON is Obi-wan. I guess the data is the droids?

Does the low-ceremony abstraction I presented seem like the kind of thing that would make that easier or more attractive for you? Let me know in the comments below, or on Twitter.

Thanks for your time, your shares, and your feedback!



P.S. This is the last scenario 😥 in this series so my next post will be letting you know that the write-up of my design notes from exploring this idea have been posted on GitHub. Thanks for your patience!

Top-Level Code Prototype: Scenario D

In Scenario A I talked about the 1-line program—a single statement that prints the value of some expression to the console.

The next logical mental exercise (for me at least) is, “Gee, what if you get tired of typing Console.WriteLine all the time. Wouldn’t it be great if a program could be a single expression and the printing could all be handled auto-magically?”. I said it was a mental exercise, not a practical one 😊

Outside of making expression evaluator bots really simple that idea isn’t actually great at all, but patterns I came up with to approach it are useful for applications of other project types and many many lines of code. The Process looks something like this:

  1. “What if a source file could be just a single expression?”
  2. “You know what’s an expression in VB? XML!”
  3. XHTML 5 is XML”
  4. <stuff>
  5. This video of me demostraing a VB ASP.NET Core 2.0 MVC app with an XML literal-based “View Engine”:

Special shout-out to book author, former VB MVP, and current Microsoftie on the WinForms team, Klaus Löffelmann for doing the heavy lifting on creating the ASP.NET Core 2.0 Web API project sample I used to make this demo. It really distilled things to the bare minimum which was a huge help to me conceptually and also a great time saver!

What about “Razor”?

Here’s the thing about “Razor” (Is it a code-name, do I need quotes?). It’s an alternate view engine to ASP.NET Web Forms that aims for a particular aesthetic. That aesthetic has value but is definitely designed around C# (not dissimilar from the way Web Forms was designed around VB and Classic ASP). The Razor that is part of ASP.NET MVC 5 supports VB but the experience isn’t a bespoke VB experience. I’m pretty sure it doesn’t support VB XML literals at all (and I understand why) and that whole Code / End Code block syntax, while… well-intended does show the seams a little. And when we talk about ASP.NET Core there’s no vbhtml at all. I’m really not saying this to knock Razor at all. I think it’s cool. And as a guy who spent 5 years spelunking two parsers, I appreciate the challenges of building and maintaining a component that understands the nuances of code while the user is typing—a  problem that is even harder when the language itself is hosting another language nested in it (XML)—while also wanting to provide a great tooling experience. (I appreciate in part because I was working on Roslyn when the ASP.NET team was working on Razor and Web Matrix and they weren’t shy about telling us about the challenges 😉). And new language versions present new conflicts if new features don’t play in the way your view engine was coded to support: I mean, can you imagine what Razor would do if VB added JSON literals?

But, we (VB programmers) are in luck. Because Microsoft already owns an incredibly well-tested, well-oiled, well-maintained component that knows the ins and outs of the VB language and seamlessly transitions between VB, and XML, and interpolated strings, infinitely nested with an incredibly rich IDE experience just deeply integrated into it. It’s always maintained, it can’t fall out of sync with new features, and it’s basically free. It’s called Roslyn; we should use it!

Once again, as I did in Scenario B, I’m asking “What if we invert the problem?” and instead of getting VB into the views, we get views into the VB. Or better yet use what’s already in VB to make something idiomatic and aesthetically pleasing just for us at a comparatively much lower cost?

WWFSD—What Would F# Do?

Over the years since its introduction I’ve been continually impressed with the grace, creativity, self-reliance, and pioneering spirit with which the F# community has approached being unique members of the broader .NET community. It’s incredibly easy to assume that there’s only one way to approach programming and that it’s whatever the newest way Microsoft has released or whatever way C# is doing it because it’s intrinsically good for everyone and the best anyone can come up with for all situations (until the next thing comes out). F# is very good at remaining rooted in its own identity while looking for solutions to the same scenarios that C# or VB coders face but in a way that is complementary to and often strengthened by F#’s unique capabilities.

For example, Razor doesn’t support F# either but when I hear F# aficionados talk about web programming they aren’t talking about Razor, they’re talking about homegrown solutions like Suave and Fable and Giraffe and CloudButt and other made up names that are built with F#’s differences (read: strengths) in mind.

It is my sincere wish that we, the VB community, learn from their many examples and that one day we too have a catalogue of colorful names on a web page somewhere built by us for us. This is my opening contribution to what I hope will be an ongoing conversation.


I’ve still got one more scenario to post and then I’ll do the full write-up on GitHub the ins-and-outs of the proposed top-level code feature that made this video possible. Web programming is just one potentially application of it that I thought up but there’s another guy who’s been thinking on this topic a lot longer than I have, VBAndCs. I really wanted this scenario to be a surprise but VBAndCs saw it all coming in my comments section all the way back in Scenario B.

I have another planned prototype in my head that would go even further on this scenario that I hope to put out later and I’m really looking forward to seeing what awesome tailor-made experiences passionate folks in the VB-Web community like VBAndCs can build given the right language tools.

Share your feedback with me, share the video with your friends. And as always, thanks and see ya later!