/flags/csharp/dotnet-build-langversion
C# LangVersion (dotnet build -p:LangVersion): fix "Feature is not available in C# N"
- tool
- C#
- command
- dotnet build
- flag
- -p:LangVersion=<version> (<LangVersion> in the .csproj)
- default
- the C# version that matches the target framework (C# 14 for net10.0)
<LangVersion> in a .csproj, or dotnet build -p:LangVersion=11 for one build, selects which C# language version the compiler accepts. Code that uses a newer feature fails with an error that names the feature and the version it needs, for example error CS9058: Feature 'collection expressions' is not available in C# 11.0. Please use language version 12.0 or greater. Without the property, the compiler uses the default version of the project's target framework.
A modern file compiled with older versions
dotnet new console -n App -o . >/dev/null 2>&1
cat > Program.cs <<'EOF'
namespace Demo;
record Point(int X, int Y);
static class Program
{
static void Main()
{
int[] nums = [1, 2, 3];
Console.WriteLine($"{nums.Length} {new Point(1, 2)}");
}
}
EOF
build() { dotnet build --no-incremental "$@" 2>&1 | grep -oE "(warning|error) CS[0-9]+[^[]*" | sort -u; echo "exit: ${PIPESTATUS[0]}"; }
for v in default 11 9 7.3 99; do
echo "== LangVersion=$v"
if [ "$v" = default ]; then build; else build -p:LangVersion=$v; fi
doneOutput
== LangVersion=default exit: 0 == LangVersion=11 error CS9058: Feature 'collection expressions' is not available in C# 11.0. Please use language version 12.0 or greater. exit: 1 == LangVersion=9 error CS8773: Feature 'file-scoped namespace' is not available in C# 9.0. Please use language version 10.0 or greater. error CS8773: Feature 'global using directive' is not available in C# 9.0. Please use language version 10.0 or greater. exit: 1 == LangVersion=7.3 error CS8630: Invalid 'nullable' value: 'Enable' for C# 7.3. Please use language version '8.0' or greater. exit: 1 == LangVersion=99 error CS1617: Invalid option '99' for /langversion. Use '/langversion:?' to list supported values. exit: 1
The default (C# 14 on net10.0) compiles everything. C# 11 rejects only the collection expression [1, 2, 3]. C# 9 already fails on the file-scoped namespace and on the global using directives that ImplicitUsings generates. C# 7.3 does not even know nullable reference types, which the template enables, so the error is about the nullable option. An unknown value fails with CS1617.
Values
| Value | Meaning |
|---|---|
| (not set) | Default for the target framework: C# 14 for net10.0, 13 for net9.0, 12 for net8.0 |
| 14, 13, 12, 11, 10, 9, 8, 7.3... | That exact version |
| latest | Latest released version the compiler supports, including minor versions |
| latestMajor | Latest released major version |
| preview | Latest preview features of the compiler |
| default | Same as latestMajor in current compilers |
Errors that point to LangVersion
| Error | Meaning |
|---|---|
| CS8773 / CS9058: Feature X is not available in C# N | Raise LangVersion, or (better) the target framework |
| CS8630: Invalid nullable value for C# 7.3 | Nullable needs C# 8.0; remove <Nullable> or raise LangVersion |
| CS1617: Invalid option for /langversion | The value is misspelled or unknown to this compiler version |
The error number depends on the feature (older features use other numbers, such as CS8370 for features of C# 8.0); the message text always names the feature and the minimum version.
Where to set it
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<!-- Usually leave LangVersion unset; pin it only when you must -->
<LangVersion>12</LangVersion>
</PropertyGroup>Put it in Directory.Build.props to give a whole repository the same version. Avoid latest in shared builds: a newer SDK on a developer machine then accepts code that the CI SDK rejects.
Pitfalls
- Pinning an old LangVersion does not make the code run on an old runtime; that is the job of
TargetFramework. - Changing only the property on the command line may not recompile in an incremental build; use
--no-incrementalordotnet build -t:Rebuildwhen experimenting, as the example does. - A missing namespace or type is not a language-version problem: CS0246 means a reference or
usingis missing.
FAQ
Which C# version does my project use if LangVersion is not set?
The default depends on the target framework: each .NET version has a default C# version (for example C# 12 for .NET 8, C# 13 for .NET 9 and C# 14 for .NET 10). Changing TargetFramework changes the language version too.
Is it safe to set LangVersion to latest on an older target framework?
It compiles, but Microsoft does not support newer language versions on older frameworks: some features need runtime or library support (default interface members, required members, ref fields) and fail or behave unexpectedly. Prefer upgrading the target framework.
How do I list the language versions my compiler supports?
The C# compiler accepts -langversion:? to print them. With the SDK, an invalid value fails with CS1617 and points to the same switch.
Sources
- learn.microsoft.comlearn.microsoft.com/en-us/dotnet/csharp/language-reference/configure-language-version
- learn.microsoft.comlearn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/language#langversion
- learn.microsoft.comlearn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-version-history