Update to the .NET language strategy

Kathleen Dollard

In 2017, we posted the strategy for .NET Languages at Microsoft as a blog post. Today, we’re publishing an updated version of the .NET Language Strategy at Microsoft Learn. It has been a long time since we have updated our strategy because our commitments to the languages that you rely on and how we think about them don’t change year to year. We’re with you for the long term.

Microsoft offers three languages on the .NET platform – C#, F#, and Visual Basic. The new .NET Language Strategy updates all three. It also includes a description that shares our perspective about each language. You’ll find additional articles with further comments on key parts of the language strategy for C#, F#, and Visual Basic. The .NET Language Strategy is available in English today and is being translated to other languages.

We’re publishing the updated strategies on Microsoft Learn to give them more permanence and make them easy to find. The previous blog post was great and we often linked to it. But, over time, it became harder to find and felt out of date. If you did find it, there was no indication that it was still our active strategy. The published version on Microsoft Learn reflects the current strategy and lets us keep it up to date. It also makes it easy to find and indicates its importance.

You won’t find big changes. We remain committed to full support for all three languages. We are also committed to open source, backwards compatibility, and aggressive language evolution for C# and F#. We took the time to reconsider, adjust and recommit to our strategy. You remain the reason we are passionate about language, and engaging with the community is a primary driver for language evolution.

Each .NET language is unique. C# is the most widely used language and the language most of .NET is written in. F# explores new language possibilities and the community provides a rich experience across platforms. We remain committed to Visual Basic and continue to invest in maintaining C# interop and Visual Studio features for folks that love Visual Basic or want a stable language.

We know that when you choose a language you make a commitment to your business and your career. We are honored that you chose us and we take that responsibility seriously. We love what we do and we think about you, about the developers that use .NET languages, in every decision we make.

The success of our languages depends on honest, open communication. The new location makes it easier to continue the conversations that the previous blog post started. Publishing our language strategies in a prominent location also keeps it front and center for us. It emphasizes the importance of our strategies, and how they guide us as we evolve the languages.

Our job every day is to make it easier for you to do your job. We know part of that is being confident in Microsoft’s commitment to the languages you love.


Discussion is closed. Login to edit/delete existing comments.

  • saint4eva 1

    NIce one. However, there is a need to limit the level of backward compatibility. No need to still support non-generic collections, for example.

    • Mystery Man 1

      PowerShell still uses non-generic collections.

    • Immo LandwerthMicrosoft employee 5

      I’m inclined to say that we’re never going to make such an impactful breaking change. We tried to start “fresh” with .NET in the Windows 8 era and it has proven to be completely unworkable. Launching a new .NET that misses core functionality like non-generic collections breaks the entire library ecosystem and is therefore a complete non-starter. Also, the benefits of removing tech like this is miniscule compared to the disruption that it causes. And lastly, this is completely independent of language evolution.

    • Heinrich Moser 1

      Generics don’t play nicely with COM interop. Of all the built-in BCL classes, we found that good old ArrayList is still the most suitable class to make .NET collections accessible to VBA code.

  • Christopher Haws 2

    Thanks for the update! While I totally get being “good stewards” towards code that is old and not breaking it, I feel like other languages have solved this problem by introducing compiler flags that allow for the language to evolve and modernize without breaking old code. I really hope that Microsoft reconsiders this approach for C#. I know that the team wants to avoid “flavors” of C# but what other options are there? Today we write way more boilerplate code than other modern languages and a lot of that is in the name of backwards compatibility (.ConfigureAwait(false), null checking on arguments, etc). Today I rely on several Fody Weavers to help eliminate some of this boilerplate, repetitive code, but they recently changed their licensing to require all devs to be an OpenCollective patron for v3.3.3 and up. While this is fine for my personal projects, this means I can no longer use this product at work without having my company somehow manage a bunch of OpenCollective patron subscriptions.

    If feature flags are an absolute no, I feel like it might be time for a new, modern .NET language. I personally wish that TypeScript.NET were a thing. Being able to use the typescript language but with .NET instead of NodeJS would be a dream come true ^_^

    • MgSam 3

      ConfigureAwait(false) is a very solvable problem- the C# team just seems to have no interest in solving it, for whatever reason. More important to work on redundant and totally superfluous features like collection literals.

    • Michael Taylor 4

      ConfigureAwait(false) is not a backwards compatibility thing and it never has been. You are clearly writing code that is backend or API heavy. This is where CA(F) is used. However there are just as many people writing front end code which mandates CA(T), which is the default. That would be like saying that C# should be async only and therefore remove support for any non-async feature. There are many problems for which async works well but there are just as many that need sync code. If you tend to write code on the other side of the default then you see it as useless but it isn’t. CA(F) is not a language feature, but a runtime feature. It is not a compatibility issue as sometimes you need the original context and sometimes you don’t. It isn’t up to the language to figure this out as the language would never know.

      • Christopher Haws 0

        FYI, I do have this configured differently for app code (ConfigureAwait(true)) vs library code (ConfigureAwait(false)) but explaining this to new developers… not simple. It is a backwards compatibility thing because MS has said many times that they made the wrong decision about the default behavior but they can’t change it because of backwards compatibility. There have been proposals to add an assembly level attribute to account for this, but as far as I can tell there is still nothing planned. Also, if you watch the videos I link below, they talk about how this “feature” probably shouldn’t even exist and that the runtime probably could have done the hard work for us (in fact David said there is a working prototype where they can write the code using only sync API’s and the runtime translates the call to be async for you).

        I also know that another artifact from early .NET that is not very “modern friendly” is events. Among other things, they don’t support async/await.

        Here are two recent interviews (one with Mads Torgersen and the other with David Fowler) and you can clearly tell that there is a huge internal struggle to modernize the language while also keeping it backwards compatible:

        I tend to agree with them that it is time to start deprecating some of the older API’s in favor of the newer ones. Analyzers with code fixes are great, but I don’t feel like they are the golden solution to this problem.

        • Michael Taylor 1

          The stuff you’re talking about is .NET, not C#. This post is about moving the language forward. Making changes to C# wouldn’t resolve the CLR issues you’re complaining about. And it still isn’t a backwards compatibility issue. The decision was made and now we’re stuck with it. Changing the “default behavior” would require all code that is currently not using the default to be modified and vice versa. That would break all existing code, not just a compatibility problem. Nevertheless this isn’t going to change and still has nothing to do with C# the language.

    • Matthias Schuster 2

      Do you know about F#, the multi paradigm, modern and non-boilerplate heavy language on dotnet?

      I heard it’s awesome ☺️

  • Paulo Pinto 2

    Thanks for the update, sadly the poor C++/CLI fellow was left out of the list.

    • Kathleen DollardMicrosoft employee 2

      That is because while C++/CLI does run on .NET, it is not managed by our team. Nothing is else is indicated by its absence.

      • Val P 2

        Although I see your position, you are posting on behalf of Microsoft, not on behalf of your team, so it would be good if you would properly present a true picture in the way customers would understand. The title of your blog post is pretty absolute, and does make one wonder what’s happening with Managed C++.

        • Jorge Morales Vidal 0

          No, Kathleen Dollard is the Principal Program Manager in .NET, it’s at the bottom of the article which, by the way, has “Update to the .NET language strategy” as its title. Here we are not talking about C++/CLI, it’s not a .NET language.

          • Paulo Pinto 0

            Apparently it is, so make up your mind,

            The .NET runtime was initially referred to as the “Common Language Runtime (CLR)”. It continues to support multiple languages, some maintained by Microsoft (e.g. C#, F#, Visual Basic, C++/CLI, and PowerShell) and some by other organizations (e.g. Cobol, Java, PHP, Python, Scheme). Many improvements are language-agnostic, which raises all boats.


      • Costa Jorge 1

        Pleaee move it to your team then, its impossible to modernize a application that heavily uses c++ cli for interop

    • John Stewien 0

      Having gone a long way down the C++/CLI path myself I can relate to your dismay. C++/CLI is handled by Microsoft’s C++ compiler. It’s not a standalone .NET language but rather a proprietary extension to the C++ language. It’s pretty much guaranteed it will never be supported by other compilers such as GCC and Clang, and it isn’t supported in the latest iteration of Microsoft’s C++ compiler that supports C++ 20. Given that no modern compiler supports it, including Microsoft’s compiler, you should probably start looking at alternatives. These alternatives being something like:
      https://github.com/AaronRobinsonMSFT/DNNE Dot Net Native Exports for calling C# from C++
      https://swig.org/ Simplified Wrapper and Interface Generator for wrapping entire C++ libraries in a generated C# interface that uses PInvoke.

      • Costa Jorge 0

        Yeah however its third party stuff. Microsoft should have first class support for interop that works everywhere. That is if they want to take our money to run code on azure they should at least do it.

        • Paulo Pinto 0

          They even mention C++/CLI on their latest post regarding why to adopt .NET, yet here they forget about it.


          So for some blog posts it matters, for others “it isn’t our team”.

          • Matteo Spreafico 0

            You’re confusing the “the languages” and “.Net”. They are 2 different stuff, even if strongly related.

  • Edison Henrique Andreassy 4

    Hello. In the strategy for Visual Basic says “VB will generally adopt a consumption-only approach and avoid new syntax”, but after couple year, we (VB programmers) still cannot consume Span or Memory. We have couple memory and performance critical applications that we could use the benefit of those types.

    • Kathleen DollardMicrosoft employee 2

      Are you having trouble calling methods that use span or return span, or referring to something that you need to create a span in order to call.

      If the second, that is what we mean by consumption only. You cannot create Span and Memory. I’m afraid that is unlikely to change.

      Our goal is to be as transparent as possible, even when the news is not what folks want to hear.

  • Stevie White 0

    Hi Kathleen,

    I do not see any major strategy shift here, or at least as far as I can tell as a developer who prefers C#. 🙂

    Below is the original article Mads posted back in 2017, in case anyone wants to compare:


    • Kathleen DollardMicrosoft employee 1

      Correct. We wanted to revisit after six years and see if anything has changed. After that work, it is largely unchanged and the blog post includes “You won’t find big changes.”

      Also, we wanted to get it in a location where you didn’t have to guess whether we had updated it. We did clarify our VB strategy in a .NET 5 era blog post, and that was certainly not easy to find.

  • li lee 3

    vb can need must should to be update to B#, that’s great,
    vb is most great lang than php on the world 🙂

  • Evolvous Limited 1

    Great Share! Thanks for the update, Kathleen.

  • 新建 孙 1

    I want to know what is the big thing about C# in the next stage?

    • Kathleen DollardMicrosoft employee 2

      Look for more on that here in this blog as we get further along in the C# 12 design.

      You can also keep up with our meetings at https://github.com/dotnet/csharplang, but those record our design process so can be messy and difficult to follow.

      • Val P 1

        Seems disappointing (at least to me) there is so much work around supporting the nullable construct, instead of adding native support for monads like Option/Either/etc. Or at least my search didn’t bring up anything planned. Maybe in c# 20.

        • Kathleen DollardMicrosoft employee 1

          Unions are hard because several constructs have been called this. You can see how often we’ve considered this searching for “discriminated” in https://github.com/dotnet/csharplang. We are looking at again for C# 12, but I can’t say whether we will settle on a design, or that the first step we will say will be monads. All of us want progress on this front.

  • Will Woo 1

    C#/.NET, my favorite language/framework, is always going to be weighed down by supporting legacy syntax/constructs.

    imho, right now energy/time is devoted to so-called “new features” like generic attributes (not generic in any meaningful sense of that word), and generic math which doesn’t address the issues of converting one numeric Type to another that have bedeviled devs (think TypeCodes and long ‘switch statements) for years.

    Meanwhile VS 2022 (latest version) still: after months, is erratic not displaying either the Property Browser, or Form design view in WinForms, and sometimes “sticks” so you can’t switch between two instances from the Wn 10 toolbar app icon as usual,

    New features in VS: colors in the Console, colored blinking carats in the editor ?

    The more and more .NET/VS hosts more new “modes,” like Maui (yet to see a usable version), the bigger it gets, and … it’s like the rest of the world.

    The ultimate syntax failure: you want a new Project for WinForms: there are two options … you no clue in the VS 2022 IDE which option leads to a project using Core, and which results in the older WF project that can use Framework =<4.8. Same thing with choosing a DLL WinForm project: create a DLL using Core, and you can't reference it in older 4.7 WF project.

    Fortunately, there are 3rd. parties, like Uno, making useful alternatives. And, companies like PostSharp demonstrating the kind of extension of the power of Attributes that MS should have developed years ago.

    all this is too much … like real-life.

  • Super Coco 8

    If Visual Basic allows .NET Core Web API projects and you show a lot of examples of that in this and others blogs, Why are there no Visual Basic .NET Core Web API templates in Visual Studio?

Feedback usabilla icon