{"id":27796,"date":"2020-04-29T13:46:09","date_gmt":"2020-04-29T20:46:09","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=27796"},"modified":"2020-05-05T09:46:56","modified_gmt":"2020-05-05T16:46:56","slug":"introducing-c-source-generators","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/introducing-c-source-generators\/","title":{"rendered":"Introducing C# Source Generators"},"content":{"rendered":"

We’re pleased to introduce the first preview of Source Generators, a new C# compiler feature that lets C# developers inspect user code and generate new C# source files that can be added to a compilation. This is done via a new kind of component that we’re calling a Source Generator.<\/p>\n

To get started with Source Generators, you’ll need to install the latest .NET 5 preview<\/a> and the latest Visual Studio preview<\/a>.\u00a0Note: to build a source generator, you currently require Visual Studio. This will change in the next .NET 5 preview.<\/strong><\/p>\n

What is a Source Generator?<\/h3>\n

Unless you’ve been closely following every prototype and proposal related to the C# language and compiler, then there’s a good chance you’re asking, “What is a Source Generator” right now. A Source Generator is a piece of code that runs during compilation and can inspect your program to produce additional files that are compiled together with the rest of your code.<\/p>\n

A Source Generator is a new kind of component that C# developers can write that lets you do two major things:<\/p>\n

    \n
  1. Retrieve a Compilation<\/em> object that represents all user code that is being compiled. This object can be inspected and you can write code that works with the syntax and semantic models for the code being compiled, just like with analyzers today.<\/li>\n
  2. Generate C# source files that can be added to a Compilation<\/em> object during the course of compilation. In other words, you can provide additional source code as input to a compilation while the code is being compiled.<\/li>\n<\/ol>\n

    When combined, these two things are what make Source Generators so useful. You can inspect user code with all of the rich metadata that the compiler builds up during compilation, then emit C# code back into the same compilation that is based on the data you’ve analyzed! If you’re familiar with Roslyn Analyzers, you can think of Source Generators as analyzers that can emit C# source code.<\/p>\n

    Source generators run as a phase of compilation visualized below:<\/p>\n

    \"Image<\/p>\n

    A Source Generator is a .NET Standard 2.0 assembly that is loaded by the compiler along with any analyzers<\/a>. It is usable in environments where .NET Standard components can be loaded and run.<\/p>\n

    Now that you know what a Source Generator is, let’s go through some of the scenarios they can improve.<\/p>\n

    Example scenarios that can benefit from Source Generators<\/h3>\n

    The most important aspect of a Source Generator isn’t what it is, but what it can enable.<\/p>\n

    Today, there are three general approaches to inspecting user code and generating information or code based on that analysis used by technologies today: runtime reflection, IL weaving, and juggling MSBuild tasks. Source Generators can be an improvement over each approach.<\/p>\n

    Runtime reflection is a powerful technology that was added to .NET a long time ago. There are countless scenarios for using it. A very common scenario is to perform some analysis of user code when an app starts up and use that data to generate things.<\/p>\n

    For example, ASP.NET Core uses reflection when your web service first runs to discover constructs you’ve defined so that it can “wire up” things like controllers and razor pages. Although this enables you to write straightforward code with powerful abstractions, it comes with a performance penalty at runtime: when your web service or app first starts up, it cannot accept any requests until all the runtime reflection code that discovers information about your code is finished running! Although this performance penalty is not enormous, it is somewhat of a fixed cost that you cannot improve yourself in your own app.<\/p>\n

    With a Source Generator, the controller discovery phase of startup could instead happen at compile time by analyzing your source code and emitting the code it needs to “wire up” your app. This could result in some faster startup times, since an action happening at runtime today could get pushed into compile time.<\/p>\n

    Source Generators can improve performance in ways that aren\u2019t limited to reflection at runtime to discover types as well. Some scenarios involve calling the MSBuild C# task (called CSC) multiple times so they can inspect data from a compilation. As you might imagine, calling the compiler more than once affects the total time it takes to build your app! We\u2019re investigating how Source Generators can be used to obviate the need for juggling MSBuild tasks like this, since Source generators don\u2019t just offer some performance benefits, but also allows tools to operate at the right level of abstraction.<\/span><\/p>\n

    Another capability Source Generators can offer is obviating the use of some “stringly-typed”<\/a> APIs, such as how ASP.NET Core routing between controllers and razor pages work. With a Source Generator, routing can<\/span> be strongly typed with the necessary strings being generated as a compile-time detail. This would<\/span> reduce the amount of times a mistyped string literal leads to a request not hitting the correct controller.<\/span><\/p>\n

    As we flesh out the API and experience writing Source Generators more, we anticipate more scenarios to become evident. We’re also planning on working with partner teams to help them adopt Source Generators if it improves their core scenarios.<\/p>\n

    Source Generators and Ahead of Time (AOT) Compilation<\/h3>\n

    Another characteristic of Source Generators is that they can help remove major barriers to linker-based and AOT (ahead-of-time) compilation optimizations. Many frameworks and libraries make heavy use of reflection or reflection-emit, such as System.Text.Json<\/em>, System.Text.RegularExpressions<\/em>, and frameworks like ASP.NET Core and WPF that discover and\/or emit types from user code at runtime.<\/p>\n

    We’ve also identified that many of the top NuGet packages<\/a> people make heavy use of reflection to discover types at runtime. Incorporating these packages is essential for most .NET apps, so the “linkability” and ability for your code to make use of AOT compiler optimizations is greatly affected. We’re looking forward to working with our wonderful OSS community to see how these packages could use source generators and improve the overall .NET ecosystem.<\/p>\n

    Hello World, Source Generator edition<\/h3>\n

    All the previous examples of source generators mentioned earlier are pretty complex. Let’s go through a very basic one to show some of the key pieces you’ll need to write your own Source Generator.<\/p>\n

    The goal is to let users who have installed this Source Generator always have access to a friendly “Hello World” message and all syntax trees available during compilation. They could invoke it like this:<\/p>\n