Working with C# 7.3 in a modern Visual Studio

Posted: (EET/GMT+2)

 

Modern Visual Studio (such as, version 2026) works perfectly well with old .NET Framework 4.x applications, but there is an interesting mismatch that is becoming easier to notice. This also happens to affect Visual Studio Code (VS Code), even if it's not my main tool.

You may be using the latest Visual Studio, the latest analyzers, and an AI coding assistant, while the application itself still speaks C# 7.3. This C# language version is common with .NET Framework 4.8 projects.

The result can be slightly confusing: Visual Studio or an AI assistant suggests a perfectly reasonable modernization, you accept it, and suddenly the project no longer compiles.

For example, older code might use a traditional using block:

using (FileStream stream = File.OpenRead(fileName))
{
    ProcessFile(stream);
}

A modern suggestion might change this to:

using FileStream stream = File.OpenRead(fileName);
ProcessFile(stream);

That is clean modern C#, but using declarations were introduced in C# 8. A project compiling as C# 7.3 cannot use them.

The same applies to target-typed new:

Dictionary<string, string> settings = new();

This kind of code requires C# 9, only available in .NET 5.0. The same applies collection expressions, which I especially like these days:

List<string> names = [];

That is much newer still. So, when maintaining an older application, it helps to keep three different versions in mind:

  • the Visual Studio and compiler tooling version
  • the C# language version selected for the project
  • the .NET Framework or .NET runtime targeted by the application.

These are all related, but they are not the same thing. A useful trick for checking the language version is to temporarily add this to a C# file:

#error version

Add this to any C# code file anywhere in the file, and then build the project. A compiler diagnostic error message of type CS8304 will tell you which compiler and C# language version are being used.

For an older .NET Framework project, you may find that the answer is C# 7.3 even though the IDE itself is completely current. The language version can also be specified explicitly in the .csproj project file:

<PropertyGroup>
    <LangVersion>7.3</LangVersion>
</PropertyGroup>

Do not automatically solve the problem by changing it to:

<LangVersion>latest</LangVersion>

This is because some newer C# syntax can work while targeting .NET Framework 4.x, but newer language features may also expect runtime or library functionality that the old target does not provide.

For production applications, changing the language version deserves the same care as any other platform modernization step you'd be making.

What about AI, then? Modern coding assistants naturally see a lot of current C#. Their preferred solution may use records, nullable reference types, file-scoped namespaces, target-typed new, collection expressions, or other syntax that did not exist when the application was written.

It can therefore be useful to state the constraint explicitly:

This is a .NET Framework 4.8 application using C# 7.3.

Do not introduce syntax or language features newer than C# 7.3.

This small piece of context can make AI-generated changes much more useful. The same rule applies when reviewing normal IDE refactorings and code suggestions.

Here are some good habits when maintaining older .NET Framework applications:

  • know which C# language version the project actually uses, and if possible, configure it explicitly
  • do not assume a modern IDE means a modern language version
  • compile after accepting modernization suggestions
  • tell AI assistants about the framework and language constraints
  • avoid changing LangVersion casually just to make one suggestion compile
  • modernize intentionally rather than one compiler error at a time.

In summary, there is nothing wrong with maintaining C# 7.3 code in a current Visual Studio version. The unusual part is that the development environment around the application keeps moving forward while the application's language generation stays where it is.

Happy C# coding!