C# language is actively developed. This means that from time to time a new version of the language is released. New versions give us access to recently added features and syntactic sugar.

The default choice of the version depends on the target framework of the project. The newest language features are only supported by the latest versions of the C# compiler.

In this article, we’ll discuss how can we centrally manage the C# language version for multiple projects.

To download the source code for this article, you can visit our GitHub repository.

Let’s start with some basics.

Setting the C# Language Version for a Project

As mentioned, the default version of the language that is available for a project is nowadays determined by the target framework. This comes without any explicit setting, although there is an optional LangVersion property that can be set in the project file.

The default choice is the latest major version that is supported by the target framework. This, however, is not equivalent to setting the <LangVersion>default</LangVersion> property in the .csproj file. 

Let’s have a quick glance at the compatibility table:

Target frameworkVersionC# language version default
.NET6.xC# 10
.NET5.xC# 9.0
.NET Core3.xC# 8.0
.NET Core2.xC# 7.3
.NET Standard2.1C# 8.0
.NET Standard2.0C# 7.3
.NET Standard1.xC# 7.3
.NET FrameworkallC# 7.3

Simply speaking, if we create a .NET Core 1.1 (C# default version 7.3) project in Visual Studio 2022, we can set the LangVersion property to either default,  latest or specific version, e.g. 10.0 and it will compile just fine. Of course, all the latest language features will be available.

For the sake of completeness, we need to be aware that it doesn’t mean we cannot have a .NET Core 1.1 project written with C# 10. The maximum supported syntax version depends on the latest C# compiler available on the machine, not the project framework.

Detailed info about differences between the version identifiers to be used in .csproj file can be found in the documentation.

Use the Directory.Build.props File for Centralized Control

In some cases, we don’t want to rely on the default choice. Controlling the language version in multiple projects would require a lot of effort. This is where the special Directory.Build.props file comes in handy.

If we create this XML file in the solution directory, any property defined in it will automatically apply to all the projects in this directory and all subdirectories.

This means we can define it in multiple places in a repository and different settings will be respected. In such a case, the settings file closer to a given project overrides the settings set higher in the folder structure:

Solution Root
 |-- Directory.Build.props
 |-- MySolution.sln
 |-- Project1
     |-- Project1.csproj
 |-- Subfolder
     |-- Directory.Build.props
     |-- Project2
         |-- Project2.csproj

The syntax used to set the language version in the Directory.Build.props file is identical to the one in the .csproj file:

<Project>
  <PropertyGroup>
    <LangVersion>latest</LangVersion>
  </PropertyGroup>
</Project>

As mentioned, we can use this file to set other project-related properties, it is not limited to language version only.

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

There’s an extra caveat in case it seems updating the Directory.Build.props file does not seem to have any effect. You might need to delete the hidden .vs directory, since Visual Studio might have cached some of the settings.

Conclusion

Summing up, we have covered three ways to control the C# language version in our projects. The implicit one, the project-specific approach, and the centralized approach utilizing the Directory.Build.props file. The centralized control can be a nice helper in large and complex repositories.