Search code examples
c#.netdocker.net-6.0c#-12.0

Setting C# language version used by Docker to build my project


I have a net6.0 project with <LangVersion> set to latest, allowing us to use latest C# features (I realize now this is probably bad practice?).

It all builds fine from within Visual Studio, but fails when building the Docker image (I'm using Visual Studio's Docker support to generate the Dockerfile for me)

Perharps unsurprisingly, I get a myriad of errors such as: error CS1525: Invalid expression term '['

I tried upgrading the dotnet images used in the Dockerfile to version 8.0 i.e. FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base and FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build: it builds fine but then the container fails at runtime You must install or update .NET to run this application. (again, unsurprisingly)

Of course, I could upgrade the project to net8.0, or remove some of these C# 12.0 features, but it's not ideal (I like those array initialization brackets :)). Are there any other options for me to look at? Like forcing the use of a particular version of MsBuild within the net6.0 Docker image so it can handle latest C#?

I develop on Windows platform, but targets Linux OS for Docker (if that matters?)

Note sure how useful it is, but here are the properties of my csproj:

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <LangVersion>latest</LangVersion>
    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
  </PropertyGroup>

Solution

  • It all builds fine from within Visual Studio, but fails when building the Docker image (I'm using Visual Studio's Docker support to generate the Dockerfile for me)

    This happens because by default The SDK uses the latest installed version, so since you have .NET 8 installed you can use the latest language features. And newer SDKs can build projects for older framework versions.

    I tried upgrading the dotnet images used in the Dockerfile to version 8.0 i.e. FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base and FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build:

    Try changing only the build image, you still are building .NET 6 project and you need to use corresponding runtime, framework-dependent apps support only minor version roll-forwarding, so your base image should still be runtime:6.0.

    I realize now this is probably bad practice?

    It is arguably not a good one. There are at least 2 types of language features/changes from the compiler point of view - "syntactic sugar" ones which do not require "direct" changes/support in the runtime and "other ones" which do. And it is not that easy to tell which one is which with the naked eye. If you are using the second type of the language feature then you will not be able to run it in older runtime (there is actually a third type of language features - which require defining some type for compiler to work, for example see How to resolve error 'NotNullWhen attribute is inaccessible due to its protection level').