.NET Framework 4.7.1 Runtime and Compiler Features

This post describes the new Runtime, Compiler and Base Class Library (BCL) improvements in the .NET Framework 4.7.1. You can try out these features by downloading the Developer Pack, described in the Welcome to the .NET Framework 4.7.1 Early Access blog post

BCL – .NET Standard 2.0 Support

.NET Framework 4.7.1 has built-in support for .NET Standard 2.0. .NET Framework 4.7.1 adds about 200 missing APIs that were part of .NET Standard 2.0 but not actually implemented by .NET Framework 4.6.1, 4.6.2 or 4.7. You can refer to details on .NET Standard on .NET Standard Microsoft docs. While libraries targeting .NET Standard 2.0 can be consumed by applications and libraries targeting .NET Framework 4.6.1 and higher, not all files that are required for .NET Standard libraries were part of .NET Framework 4.6.1. In fact, .NET Framework 4.6.1 was shipped before .NET Standard 2.0 was even designed. That’s why building an application targeting .NET Framework 4.6.1, as well as .NET Framework 4.6.2 and 4.7, will have to deploy additional .NET Standard 2.0 support files.

Experience in .NET Framework 4.6.1 through 4.7
  • If you use Visual Studio 2017 15.3 or higher, the .NET Standard 2.0 support files are automatically copied to the application’s output folder.
  • If you use Visual Studio 2015 and use NuGet 3.6, we will prompt you to install a support package which will handle copying the support files to the output directory.
Experience in .NET Framework 4.7.1
  • These support files no longer have to be deployed with the application – they are built right into the .NET Framework itself.
  • This also removes the need for binding redirects when using .NET Standard libraries on .NET Framework because the CLR automatically unifies version numbers of assemblies that are part of the platform.

Runtime – GC Performance Improvements

.NET Framework 4.7.1 brings in changes in Garbage Collection (GC) to improve the allocation performance, especially for Large Object Heap (LOH) allocations. This is due to an architectural change to split the heap’s allocation lock into 2, for Small Object Heap (SOH) and LOH. Applications that make a lot of LOH allocations, should see a reduction in allocation lock contention, and see better performance. These improvements allow LOH allocations while Background GC (BGC) is sweeping SOH. Usually the LOH allocator waits for the whole duration of the BGC sweep process before it can satisfy requests to allocate memory. This can hinder performance. You can observe this problem in PerfView’s GCStats where there is an ‘LOH allocation pause (due to background GC) > 200 msec Events’ table. The pause reason is ‘Waiting for BGC to thread free lists’. This feature should help mitigate this problem.

Compiler – ValueTuple is Serializable

The System.ValueTuple types in .NET Framework 4.7.1 are now marked as Serializable, which allows binary serialization as shown in the example below. Since the syntax for C# 7.0 and VB 15.5 tuple types, for example, (int, string) relies on System.ValueTuple, this should make migrating from System.Tuple to using the new tuple syntax easier.

Compiler – Support for ReadOnlyReferences

.NET Framework 4.7.1 adds initial support for the ReadOnlyReferences C# 7.2 language feature, which  is coming in a future Visual Studio 2017 Update. .NET Framework 4.7.1 introduces the IsReadOnlyAttribute for ReadOnlyReferences feature. This attribute will be used by the compiler to mark members that have readonly-ref return types or parameters. If the compiler is running against an older .NET Framework version, it will generate this attribute and embed it’s definition in the compiled assembly. The following example illustrates C# 7.2 code that can make use of this attribute.

Compiler – Support for Runtime Feature Detection

This new API provides a way to detect whether a particular runtime supports a certain feature or not. At compile time the API provides a way to do that statically through reflection. Whenever the compiler needs to check for runtime support, it would look for the corresponding well-known enum member, for instance, System.Runtime.CompilerServices.RuntimeCapabilities.SupportsDefaultImplementation. If the member exists, then the feature check is successful or the feature is supported. The value for that enum member is ignored.

At runtime the check for feature support is done by calling a static method. This is enabled by the addition of the framework type RuntimeFeatures. Tools can query it by calling the static method bool IsSupported(string) to check whether the feature is supported or not, by passing in the string name for a given feature. For example, RuntimeFeatures.IsSupported(“FixedGenericAttributes”).

Following example illustrates C# 7.2 code that can make use of this attribute.

Runtime – Support for Portable PDBs

This feature adds support for Portable PDBs in the .NET Framework. Libraries that generate code at runtime, like C# Scripting, would benefit from being able to detect whether the runtime supports Portable PDBs or not. This is because they could emit Portable PDBs instead of Windows PDBs. Emitting Portable PDBs has performance benefits; it is faster and has much smaller memory footprint. In absence of this new API the library would need to resort to hard-coding build numbers of the mscorlib or conservatively assume that .NET Framework doesn’t support Portable PDBs. In addition RuntimeFeature.IsSupported method would be changed to return true if ‘PortablePdb’ is passed to it. Following sample illustrates how this can be passed.

Closing

Try out these new features in .NET Framework 4.7.1 Early Access build shared and please provide your feedback by reporting an issue at the .NET Framework Early Access GitHub repository