Mastering Code Generation and Compile-Time Intelligence in Modern C#
C# 14 introduces significant enhancements to source generators and compile-time features, enabling developers to produce code automatically, enforce patterns, and perform checks at compile time.
These features reduce boilerplate, prevent runtime errors, and improve maintainability, all while keeping code strongly typed and fully integrated with tooling.
Source generators allow your compiler to inject C# code during compilation, giving you the power to generate repetitive code, scaffolding, or diagnostic helpers – without runtime reflection or additional libraries.
🔹 What Are Source Generators?
A source generator is a compiler extension that runs during compilation, producing C# source code that becomes part of the compilation process.
Key points:
- Runs at compile time, not runtime.
- Generates fully typed C# code, recognized by the compiler.
- Can be used for boilerplate elimination, code validation, and compile-time reflection.
Basic Example:
// Define a generator (simplified)
[Generator]
public class HelloWorldGenerator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
var source = @"
namespace Generated
{
public static class HelloWorld
{
public static void SayHello() => System.Console.WriteLine(""Hello from generated code!"");
}
}";
context.AddSource("HelloWorldGenerator", source);
}
public void Initialize(GeneratorInitializationContext context) { }
}
Usage:
Generated.HelloWorld.SayHello(); // Output: Hello from generated code!
✅ Explanation:
- The generator produces real C# code at compile time.
- The compiler sees it as if it were written manually.
- This allows IDE tooling, IntelliSense, and static analysis to recognise the generated code.
🔹 1. Compile-Time Constants and Improvements
C# 14 enhances compile-time evaluation and constant handling.
You can now use compile-time expressions in more scenarios, enabling source generators to produce safer, more predictable code.
const int MaxCount = 10;
C# 14 Enhancement:
- Allows richer compile-time expressions for arrays, attributes, and initializers.
- Enables source generators to validate or generate code based on constants.
✅ Benefit: Reduces runtime errors and improves compiler-assisted code correctness.
🔹 2. Partial Methods with Implementations
C# 14 allows partial methods to include implementations, previously limited to declarations.
public partial class User
{
partial void OnCreated();
public User() => OnCreated();
}
public partial class User
{
partial void OnCreated() => Console.WriteLine("User created!");
}
✅ Benefit:
- Source generators can create hooks and scaffolding, while allowing developers to implement behavior separately.
- Improves clean separation of generated vs. manual code.
🔹 3. Attributes for Code Generation
C# 14 introduces enhanced attribute support for guiding source generators:
[AutoNotify] // Custom attribute
public string Name { get; set; }
A source generator can now scan for attributes and generate code automatically, e.g., implementing INotifyPropertyChanged:
public partial class Person
{
public string Name { get; set; } // Generator creates OnPropertyChanged automatically
}
✅ Explanation:
- Attributes act as markers for code generation.
- Minimises repetitive boilerplate like event invocation or property scaffolding.
🔹 4. Global Using Directives in Source-Generated Code
C# 14 improves namespace management in generated code via global using directives:
global using System;
global using System.Collections.Generic;
✅ Benefit:
- Ensures that generated files compile without extra usings.
- Reduces conflicts and simplifies generator output.
🔹 5. Compile-Time Diagnostics and Validation
Source generators in C# 14 can produce diagnostic warnings and errors at compile time:
context.ReportDiagnostic(Diagnostic.Create(
new DiagnosticDescriptor(
"SG001",
"Property is missing required attribute",
"Property '{0}' must have [AutoNotify]",
"Usage",
DiagnosticSeverity.Warning,
true),
Location.None,
propertyName));
✅ Benefit:
- Catch errors before runtime.
- Improves code quality and enforces coding standards automatically.
🔹 6. Enhanced Partial Class and Namespace Integration
Generated code can now extend existing classes, structs, and namespaces seamlessly:
namespace MyApp.Models
{
public partial class Customer { } // Base class
}
// Generated code
namespace MyApp.Models
{
public partial class Customer
{
public string FullName => FirstName + " " + LastName;
}
}
✅ Benefit:
- Developers maintain manual logic, while generators add features.
- Clean separation of generated and handwritten code.
🔹 7. Practical Example: AutoNotify Generator
Manual Code Before C# 14 Enhancements:
public class Person : INotifyPropertyChanged
{
private string _name;
public string Name
{
get => _name;
set
{
_name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
With Source Generator in C# 14:
[AutoNotify]
public partial class Person
{
public string Name { get; set; }
}
- The generator automatically implements the backing field, getter/setter, and PropertyChanged invocation.
- Compile-time generation ensures type safety, minimal boilerplate, and IDE support.
🔍 Performance Considerations
| Strategy | Description | Example |
|---|---|---|
| Use partial methods | Reduce overhead for optional code hooks | partial void OnCreated(); |
| Limit generator output | Avoid huge generated files | Generate only necessary code |
| Validate inputs at compile time | Catch mistakes early | Diagnostics from source generator |
| Target typed usings | Reduce namespace collisions | global using System; |
✅ Tip: Carefully structure generated code to avoid compilation slowdowns and excessive dependency chains.
🔹 8. Summary
| Feature | Description | Example |
|---|---|---|
| Source Generators | Compile-time code generation | [Generator] produces classes automatically |
| Partial Methods | Partial methods can have implementations | partial void OnCreated() |
| Attributes | Guide generation and automation | [AutoNotify] |
| Compile-Time Diagnostics | Enforce rules at build time | context.ReportDiagnostic(...) |
| Global Using Integration | Simplify generated file namespaces | global using System; |
| Separation of Code | Combine manual and generated logic | Partial classes, nested namespaces |
Final Thoughts
C# 14’s source generators and compile-time enhancements empower developers to automate repetitive patterns, enforce consistency, and generate code safely.
By integrating these features:
- You reduce boilerplate and runtime errors.
- Achieve clean separation of generated and handwritten logic.
- Leverage compile-time diagnostics to enforce coding standards.
- Improve maintainability and productivity in large, type-safe codebases.
Mastering source generators in C# 14 transforms the way you write and maintain code, combining compile-time intelligence with the flexibility of C# to create robust, modern, and scalable applications.