Does C# 8 Support the .Net Framework

Does C# 8 support the .NET Framework?

Yes, C# 8 can be used with the .NET Framework and other targets older than .NET Core 3.0/.NET Standard 2.1 in Visual Studio 2019 (or older versions of Visual Studio if you install a NuGet package).

The only thing required is to set language version to 8.0 in the csproj file. You can also do this in Directory.Build.props to apply it to all projects in your solution. Read below for how to do this in Visual Studio 2019, version 16.3 and newer.

Most - but not all - features are available whichever framework is targeted.



Features that work

The following features are syntax changes only; they work regardless of framework:

  • Static local functions
  • Using declarations
  • Null-coalescing assignment
  • Readonly members
  • Disposable ref structs
  • Positional patterns
  • Tuple patterns
  • Switch expressions
  • Nullable reference types are also supported, but the new nullable attributes required to design the more complex nullable use cases are not. I cover this in more detail further down in the "gory details" section.

Features that can be made to work

These require new types which are not in the .NET Framework. They can only be used in conjunction with "polyfill" NuGet packages or code files:

  • Asynchronous streams - Microsoft.Bcl.AsyncInterfaces
  • Indices and ranges

Default interface members - do not, cannot, and never will work

Default interface members won't compile under .NET Framework and will never work because they require runtime changes in the CLR. The .NET CLR is now frozen as .NET Core is now the way forward.

For more information on what does and doesn't work, and on possible polyfills, see Stuart Lang's article, C# 8.0 and .NET Standard 2.0 - Doing Unsupported Things.



Code

The following C# project targetting .NET Framework 4.8 and using C# 8 nullable reference types compiles in Visual Studio 16.2.0. I created it by choosing the .NET Standard Class Library template and then editing it to target .NET Framework instead:

.csproj:

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net48</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

.cs:

namespace ClassLibrary1
{
public class Class1
{
public string? NullableString { get; set; }
}
}

I then tried a .NET Framework 4.5.2 WinForms project, using a legacy .csproj format, and added the same nullable reference type property. I changed the language type in the Visual Studio Advanced Build settings dialog (disabled in 16.3) to latest and saved the project. Of course as this point it doesn't build. I opened the project file in a text editor and changed latest to preview in the build configuration PropertyGroup:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<LangVersion>preview</LangVersion>

I then enabled support for nullable reference types by adding <Nullable>enable</Nullable> to the main PropertyGroup:

<PropertyGroup>
<Nullable>enable</Nullable>

I reloaded the project, and it builds.



Visual Studio 2019

There has been a major change in the RTM version of Visual Studio 2019 version 16.3, the launch version for C# 8.0: the language selection dropdown has been disabled:

Sample Image

Microsoft's rationale for this is:

Moving forward, ... each version of each framework will have a single
supported and default version, and we won't support arbitrary
versions. To reflect this change in support, this commit permanently
disables the language version combo box and adds a link to a document
explaining the change.

The document which opens is C# language versioning. This lists C# 8.0 as the default language for .NET Core 3.x ONLY. It also confirms that each version of each framework will, going forward, have a single supported and default version and that the framework-agnosticism of the language can no longer be relied on.

The language version can still be forced to 8 for .NET Framework projects by editing the .csproj file.



The gory details

When this answer was first written, C# 8 was in preview and a lot of detective work was involved. I leave that information here for posterity. Feel free to skip it if you don't need to know all the gory details.

The C# language has historically been mostly framework neutral - i.e. able to compile older versions of the Framework - although some features have required new types or CLR support.

Most C# enthusiasts will have read the blog entry Building C# 8.0 by Mads Torgersen, which explains that certain features of C# 8 have platform dependencies:

Async streams, indexers and ranges all rely on new framework types
that will be part of .NET Standard 2.1... .NET Core 3.0 as well as
Xamarin, Unity and Mono will all implement .NET Standard 2.1, but .NET
Framework 4.8 will not. This means that the types required to use
these features won’t be available on .NET Framework 4.8.

This looks a bit like Value Tuples which were introduced in C# 7. That feature required new types - the ValueTuple structures - which were not available in NET Framework versions below 4.7 or .NET Standard older than 2.0. However, C# 7 could still be used in older versions of .NET, either without value tuples or with them by installing the System.ValueTuple Nuget package. Visual Studio understood this, and all was fine with the world.

However, Mads also wrote:

For this reason, using C# 8.0 is only supported on platforms that implement .NET Standard 2.1.

...which if true would have ruled out using C# 8 with any version of the .NET Framework, and indeed even in .NET Standard 2.0 libraries which only recently we were encouraged to use as a baseline target for library code. You wouldn't even be able to use it with .NET Core versions older than 3.0 as they too only support .NET Standard 2.0.

The investigation was on! -

  • Jon Skeet has an alpha version of Noda-Time using C# 8 ready to go which targets .NET Standard 2.0 only. He is clearly expecting C# 8/.NET Standard 2.0 to support all frameworks in the .NET family. (See also Jon's blog post "First steps with nullable reference types").

  • Microsoft employees have been discussing the Visual Studio UI for C# 8 nullable reference types on GitHub, and it is stated that they intend to support the legacy csproj (pre-.NET Core SDK format csproj). This is a very strong indication that C# 8 will be usable with the .NET Framework. [I suspect they will backtrack on this now that the Visual Studio 2019 language version dropdown has been disabled and .NET has been tied to C# 7.3]

  • Shortly after the famous blog post, a GitHub thread discussed cross-platform support. An important point which emerged was that .NET Standard 2.1 will include a marker that denotes that default implementations of interfaces is supported - the feature requires a CLR change that will never be available to the .NET Framework. Here's the important bit, from Immo Landwerth, Program Manager on the .NET team at Microsoft:

Compilers (such as C#) are expected to use the presence of this field to decide whether or not to allow default interface implementations. If the field is present, the runtime is expected to be able to load & execute the resulting code.

  • This all pointed to "C# 8.0 is only supported on platforms that implement .NET Standard 2.1" being an oversimplification, and that C# 8 will support the .NET Framework but, as there is so much uncertainty, I asked on GitHub and HaloFour answered:

IIRC, the only feature that definitely won't appear on .NET Framework is DIM (default interface methods) as that requires runtime changes. The other features are driven by the shape of classes that might never be added to the .NET Framework but can be polyfilled through your own code or NuGet (ranges, indexes, async iterators, async disposal).

  • Victor Derks commented that "The new nullable attributes required to design the more complex nullable use cases are only available in System.Runtime.dll that ships with .NET Core 3.0 and .NET Standard 2.1... [and] incompatible with .NET Framework 4.8"

  • However, Immo Landwerth commented that "The vast majority of our APIs didn't need any custom attributes as the types are either fully generic or not-null" under the article Try out Nullable Reference Types

  • Ben Hall raised the issue Availability of nullable attributes outside of Core 3.0 on GitHub, with the following comments from Microsoft employees being of note:

C# 8 will be fully supported on .net core 3.0 and .net standard 2.1 only.
If you manually edit the project file to use C# 8 with .net core 2.1,
you are in unsupported territory. Some C# 8 features will happen to
work well, some C# 8 features will work not too well (e.g. poor
performance), some C# 8 features will work with extra hacks, and some
C# 8 features will not work at all. Very complex to explain. We do not
actively block it so the expert users who can navigate through it can
do so. I would not recommend this unsupported mix&match to be used
broadly.

(Jan Kotas)

People like you who are willing understand -- and work around them --
are free to use C# 8. The point is, not all language features will work
on down-level targets.

(Immo Landwerth)



Caveat emptor

The C# 8/.NET Framework combination is not officially supported by Microsoft. It is, they say, for experts only.

C# 8 features in .NET Framework 4.7.2

Some features of C# 8.0 are available in .NET Framework, but not all of them. If you can compile locally, your build server should be able to compile too. But note: C# 8.0 is only officially supported on frameworks implementing .NET Standard 2.1 (which the .NET Framework will never do). So while it might work, there might also be problems.

Don't use LangVersion preview any more. C# 8.0 was released with VS2019 16.3. Use LangVersion latest (or latestMajor or 8.0) to get C# 8.0 support in a project that doesn't support it by default (see C# language versioning).

To do that, make sure that your csproj files contain the property <LangVersion>latest</LangVersion>. You need to manually edit the csproj files to do this. The UI to change the language version was disabled in VS2019 16.3 because each target framework now officially only supports a single language version.

Relationship between C# 8.0, NET Core 3.0 and Visual Studio

Update after release of .NET Core 3

Some features added in C# 8.0 require .NET Core 3.0, so these have a tighter relationship than C#/.NET had before. The pair can be acquired as a workload through VS, but keep in mind C# 8.0 and .NET Core 3.0 don't require VS; you can use these in other IDEs.

The C# language versioning document describes the language/.NET relationships in more detail.

For some pragmatic details, you can read how to target C# 8.0 in Visual Studio.

Old Answer

Take a look at An update to C# versions and C# tooling, which provides a good insight about the language as it relates to projects in Visual Studio.

In particular,

The default language version chosen in this scenario is Preview. The C# 8.0 features you have access to are based entirely on the version of the compiler (and thus the .NET SDK) that you are using. As you use future previews, you may get more (or slightly tweaked) features. When you build a project, the .NET SDK will emit a warning that this is all still in preview.

In answer to

What is the relationship between C# 8.0, NET Core 3.0 and Visual Studio?

The relationship between language, SDK, and Visual Studio version are much looser than they used to be. The language can evolve independent of .NET in any of its incarnations. That doesn't mean that will always be true. Visual Studio too is independent of language and framework. If you take a look at the Visual Studio Installer, you will see that language and .NET support are "workloads" that can be installed. The SDK exposes the language features and VS offers the tooling.

If you're going with VS 2017 for now, take a look at

  • SO Q&A on .NET Core 3.0 and VS 2017
  • This article on C# 8.0 in VS 2017

As a followup, I'm also confused as to what a new language version actually is in terms of physical deployment

It's the SDK that contains the compiler that can create the assemblies from C# 8.0 source.

Is it new assemblies deployed as part of a new visual studio deploy, or part of a net core sdk install or something else?

Part of the SDK, see above. This means nothing is "deployed" in addition to your code. Your code, whatever the version, targets a version of .NET. That said, the targeted version of .NET must exist on the machine or container.

Does C# 8 need to be added to both full framework and .NET Core?

It doesn't "need to be added". The newer versions of this framework (4.8) and SDK (.NET Core 3.0) come with C# 8.0 support.

.NET Framework 4.8 seems to use C# version older than 7

I used a comment to formulate the answer. I checked the csproj file and searched for LangVersion.

<LangVersion>6</LangVersion>

Removing the line solved the problem.

The language version nowadays is based on the .NET framework version and is not separately specified.

You cannot set the language version in the projects advanced properties, but the setting seems to be respected despite that.

What are the correct version numbers for C#?


C# language version history:

These are the versions of C# known about at the time of this writing:

  • C# 1.0 released with .NET 1.0 and VS2002 (January 2002)
  • C# 1.2 (bizarrely enough); released with .NET 1.1 and VS2003 (April 2003). First version to call Dispose on IEnumerators which implemented IDisposable. A few other small features.
  • C# 2.0 released with .NET 2.0 and VS2005 (November 2005). Major new features: generics, anonymous methods, nullable types, and iterator blocks
  • C# 3.0 released with .NET 3.5 and VS2008 (November 2007). Major new features: lambda expressions, extension methods, expression trees, anonymous types, implicit typing (var), and query expressions
  • C# 4.0 released with .NET 4 and VS2010 (April 2010). Major new features: late binding (dynamic), delegate and interface generic variance, more COM support, named arguments, tuple data type and optional parameters
  • C# 5.0 released with .NET 4.5 and VS2012 (August 2012). Major features: async programming, and caller info attributes. Breaking change: loop variable closure.
  • C# 6.0 released with .NET 4.6 and VS2015 (July 2015). Implemented by Roslyn. Features: initializers for automatically implemented properties, using directives to import static members, exception filters, element initializers, await in catch and finally, extension Add methods in collection initializers.
  • C# 7.0 released with .NET 4.7 and VS2017 (March 2017). Major new features: tuples, ref locals and ref return, pattern matching (including pattern-based switch statements), inline out parameter declarations, local functions, binary literals, digit separators, and arbitrary async returns.
  • C# 7.1 released with VS2017 v15.3 (August 2017). New features: async main, tuple member name inference, default expression, and pattern matching with generics.
  • C# 7.2 released with VS2017 v15.5 (November 2017). New features: private protected access modifier, Span<T>, aka interior pointer, aka stackonly struct, and everything else.
  • C# 7.3 released with VS2017 v15.7 (May 2018). New features: enum, delegate and unmanaged generic type constraints. ref reassignment. Unsafe improvements: stackalloc initialization, unpinned indexed fixed buffers, custom fixed statements. Improved overloading resolution. Expression variables in initializers and queries. == and != defined for tuples. Auto-properties' backing fields can now be targeted by attributes.
  • C# 8.0 released with .NET Core 3.0 and VS2019 v16.3 (September 2019). Major new features: nullable reference-types, asynchronous streams, indices and ranges, readonly members, using declarations, default interface methods, static local functions, and enhancement of interpolated verbatim strings.
  • C# 9.0 released with .NET 5.0 and VS2019 v16.8 (November 2020). Major new features: init-only properties, records, with-expressions, data classes, positional records, top-level programs, improved pattern matching (simple type patterns, relational patterns, logical patterns), improved target typing (target-type new expressions, target typed ?? and ?), and covariant returns. Minor features: relax ordering of ref and partial modifiers, parameter null checking, lambda discard parameters, native ints, attributes on local functions, function pointers, static lambdas, extension GetEnumerator, module initializers, and extending partial.
  • C# 10.0 released with .NET 6.0 (November 2021). Major new features: record structs, struct parameterless constructors, interpolated string handlers, global using directives, file-scoped namespace declarations, extended property patterns, const interpolated strings, mixed assignment and declaration in deconstruction, async method builders (via attributes) for individual methods, the CallerArgumentExpression attribute for parameters, enhanced #line pragmas.
  • C# 11.0 will be released with .NET 7.0 (Date to be annonced, already testable). Major new features: file-scoped types, generic math support, auto-default structs, pattern match Span<char> on a constant string, extended nameof scope, numeric IntPtr, UTF-8 string literals, required members, ref fields and scoped ref, raw string literals, improved method group conversion to delegate, warning wave 7, generic attributes, newlines in string interpolation expressions, list patterns

In response to the OP's question:

What are the correct version numbers for C#? What came out when? Why can't I find any answers about C# 3.5?

There is no such thing as C# 3.5 - the cause of confusion here is that the C# 3.0 is present in .NET 3.5. The language and framework are versioned independently, however - as is the CLR, which is at version 2.0 for .NET 2.0 through 3.5, .NET 4 introducing CLR 4.0, service packs notwithstanding. The CLR in .NET 4.5 has various improvements, but the versioning is unclear: in some places it may be referred to as CLR 4.5 (this MSDN page used to refer to it that way, for example), but the Environment.Version property still reports 4.0.xxx.

As of May 3, 2017, the C# Language Team created a history of C# versions and features on their GitHub repository: Features Added in C# Language Versions. There is also a page that tracks upcoming and recently implemented language features.

How to use new c# 8.0 features in Razor views

OK so, there are some things that needs to be clarified first.

According to this answer C# language version is tied with the framework, and C# 8.0 is fully available to all language that support .Net Standard 2.1.
.NET Framework 4.7.2 and below does not support .NET Standard 2.1 and it will not be the case in the future.

In the meantime there is a way to use C# 8.0 if you specify the LangVersion in any .csproj project file:

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net48</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

This will enable C# 8.0 and some non-tied framework features will be available to you. Check the link answer to know which one.

Finally to answer my own question, at this time, no, there is no way to use any of the C# 8.0 features inside a Razor view. The run-time compilation seems to be done with a package named Microsoft.CodeDom.Providers.DotNetCompilerPlatform so the only way would be to update that package to allow some of the new features to be used.

I will update that answer as soon as I get more information.

How can I use C# 8 with Visual Studio 2017?

Going forward, Microsoft want to tie C# language versions more closely to framework versions than they have in the past. They really only want you to be using C# 8 with .NET Core 3.x and .NET Standard 2.1 projects, and that means using Visual Studio 2019. My answer to Does C# 8 support the .NET Framework? has all the gory details.

However, if you really want to you can now use C# 8 in Visual Studio 2017 by using the same trick that brings C# 7 to Visual Studio 2015: install the latest version of the Microsoft.Net.Compilers Nuget package into the project. It works, but of course VS 2017 doesn't know about C# 8 syntax so it doesn't look very pretty. Here's a screenshot showing that VS 2017 is able to compile a small test library using nullable reference types and a static local method (both of which are C# 8 features):

Sample Image


Here's the .csproj and code if you want to try it:

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net452</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Net.Compilers" Version="3.3.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>

-

using System;

namespace CSharp8Test
{
public class Class1
{
public string? NullableString { get; } = "Test";

public static void Test()
{
Console.WriteLine(Test2());
static int Test2() => 5;
}
}
}


Related Topics



Leave a reply



Submit