A .NET 9 console application that converts C# primary constructors (introduced in C# 12) to standard constructors.
The primary purpose of this tool is to enable Doxygen documentation generation for C# projects that use primary constructors. Doxygen does not currently support C# 12 primary constructor syntax, which can cause documentation generation to fail or produce incomplete results. This tool acts as a filter to convert primary constructors to standard constructors that Doxygen can understand.
This tool does not modify your source code. It only modifies the input Doxygen receives to generate the documentation.
-
Unzip to any folder on the computer (the example below uses
c:\Tools\PrimaryConstructorConverter\) -
Update your Doxyfile as follows (modify the executable)
INPUT_FILTER =
FILTER_PATTERNS = *.cs="c:\Tools\PrimaryConstructorConverter\PrimaryConstructorConverter.exe"
FILTER_SOURCE_FILES = YES
- Replace the path with the actual path to the
PrimaryConstructorConverter.exeon your system - On Linux/macOS, use:
dotnet /path/to/PrimaryConstructorConverter.dll - The
FILTER_SOURCE_FILES = YESsetting is required for the filter to work - The original source files remain unchanged; only the documentation generation is affected
Doxygen filters must not add or remove lines from the source code, as this affects code anchors and cross-references in the generated documentation. However, this tool necessarily adds lines (fields, constructors) when converting primary constructors, which can cause the following issues:
- Source code links in documentation may point to incorrect line numbers
- Code anchors and cross-references may be misaligned
- The "Go to source" feature in HTML documentation may jump to wrong locations
Option 1: Don't enable the source code browser (Recommended)
SOURCE_BROWSER = NO
This disables source code browsing but still generates full API documentation.
Option 2: Accept the line number offset Keep source browsing enabled and accept that line numbers in documentation won't match the actual source files. The documentation will still be functionally complete.
Option 3: Pre-convert your source files If you need accurate line numbers, convert your source files permanently using the command-line interface, commit the converted versions, and disable the filter:
# Convert a file
PrimaryConstructorConverter MyClass.cs > MyClass_converted.cs
# Then use normal Doxygen without filtersThis tool converts C# primary constructors to standard constructors for:
- Classes: Converts primary constructor parameters to private readonly fields with a standard constructor
- Structs: Converts primary constructor parameters to private readonly fields with a standard constructor
- Records: Converts primary constructor parameters to public properties with init accessors and a standard constructor
Before:
public class Person(string firstName, string lastName, int age)
{
public string GetFullName() => $"{firstName} {lastName}";
public bool IsAdult() => age >= 18;
}After:
public class Person
{
private readonly string _firstName;
private readonly string _lastName;
private readonly int _age;
public Person(string firstName, string lastName, int age)
{
_firstName = firstName;
_lastName = lastName;
_age = age;
}
public string GetFullName() => $"{_firstName} {_lastName}";
public bool IsAdult() => _age >= 18;
}Before:
public record Product(string Name, decimal Price, int Stock);After:
public record Product
{
public string Name { get; init; }
public decimal Price { get; init; }
public int Stock { get; init; }
public Product(string Name, decimal Price, int Stock)
{
Name = Name;
Price = Price;
Stock = Stock;
}
}Before:
public struct Point(int x, int y)
{
public double GetDistance() => Math.Sqrt(x * x + y * y);
}After:
public struct Point
{
private readonly int _x;
private readonly int _y;
public Point(int x, int y)
{
_x = x;
_y = y;
}
public double GetDistance() => Math.Sqrt(_x * _x + _y * _y);
}- .NET 9.0 or later
dotnet build -c ReleaseMIT License. This project is free to use, modify, and distribute. See the LICENSE file for details.