What are C# Source Generators?
Developers across the globe were looking for a new capability in the C# compiler that allowed them to evaluate user code and generate additional C# source files (which in turn can be included in a compilation).
Their request was granted when a new type of component known as a Source Generator was created.
In this post, let us understand everything you need to know about C# source generators and how it is useful to these developers.
Table of contents
- What is a Source Generator?
- Scenarios benefitting from Source Generator
- Source Generator and Ahead Of Time (AOT) compilation
- What's next for Source Generators?
What is a Source Generator?
Unless you've been following carefully every prototype and proposal related to the C# language, you might be asking yourself right now, "What is a Source Generator?" In simple language, a Source Generator is a piece of code that runs during compilation and inspects your program to generate additional files that are compiled alongside the rest of your code.
A Source Generator allows them to achieve two things:
- Get a Compilation object that represents all the user code being compiled. This object can be examined, and you can write code that uses the syntax and semantic models for the code being compiled, similar to how analyzers function today.
- Produce C# source files that can be inserted into a Compilation object during the compilation process. In other words, while the code is being generated, you can submit a new source code as input.
These two factors, when combined, make Source Generators extremely beneficial. You can inspect user code with all of the rich metadata that the compiler generates during compilation, then emit C# code back into the same compilation based on the data you analyzed! Source Generators are similar to Roslyn Analyzers in that they are analyzers that can generate C# source code.
Source generators are used during the compilation step, which is depicted below:
A Source Generator is a.NET Standard 2.0 assembly that is loaded together with any analyzers by the compiler. It can be used in situations that support the loading and running of.NET Standard components.
Scenarios benefitting from Source Generator
What matters most about a Source Generator is what it can do, not what it is. Runtime reflection, IL weaving, and juggling MSBuild tasks are three common ways to evaluate user code and create information/code based on the analysis utilized by technologies today. Source Generators have the potential to outperform all other methods.
Runtime reflection is a strong feature that was recently added to.NET. It can be used in a variety of situations. When an app starts up, a common situation is to analyze the user code and use the results to build something.
When your web service initially runs, for example, ASP.NET Core uses reflection to find structures you've defined so it can "wire together" things like controllers and razor pages. Although this allows you to write simple code with powerful abstractions, it has a performance penalty at runtime: when your web service or app first starts up, it will not be able to accept any requests until all of the runtime reflection code that discovers information about your code has finished running! Although the performance penalty isn't significant, it is a sunk cost that you can't eliminate in your software.
The controller discovery portion of startup might instead happen at compile time with a Source Generator, which analyzes your source code and emits the code needed to "wire up" your app. Because an activity that occurs at runtime today may be shifted into compile-time, this could result in faster startup times.
Source Generators can increase efficiency in a variety of methods, including using runtime reflection to find types. Some cases require repeated calls to the MSBuild C# task (named CSC) to inspect data from a compilation. As you may expect, using the compiler multiple times will have an impact on the overall time it takes to develop your program.
Source Generators can be utilized to eliminate the need to juggle MSBuild jobs like this because Source Generators not only improve performance but also allow tools to work at the appropriate level of abstraction.
Another advantage of Source Generators is that they can eliminate the need for some "stringly-typed" APIs, such as the routing between controllers and razor pages in ASP.NET Core. Routing can be strongly typed with a Source Generator, with the appropriate strings generated as a compile-time detail. This would cut down on the number of times a mistyped string causes a request to be sent to the wrong controller.
Source Generator and Ahead Of Time (AOT) compilation
Source Generators can also help remove substantial roadblocks to linker-based and AOT (Ahead-Of-Time) compilation improvements. Many frameworks and libraries, such as System, make extensive use of reflection or reflection-emitting.
Many of the most popular NuGet packages heavily rely on reflection to find types at runtime. Because including these packages is required for most.NET projects, your code's "linkability" and ability to make use of AOT compiler optimizations is severely harmed.
Source generators are a vital feature that has made the lives of developers better. You can use this functionality to modernize repetitive coding patterns in a secure and performant way. I strongly advise you to give it a shot. When you generate code, you might be astonished at how much you can achieve.