Mono 5.0.0 Release Notes

These notes are for a current or upcoming PREVIEW RELEASE and might not reflect the final release.


Release History

  • - Alpha 2 (11 Apr 2017)
  • - Alpha 1 (06 Apr 2017)


In Depth

C# compiler


The Roslyn C# compiler is now available on Mono and it’s called csc. It’s the same compiler available on Windows / Visual Studio with full support for C# 7. Both msbuild and xbuild have been updated to call the csc compiler under the hood instead of mcs.

Replacing mcs with csc in user scripts should be straightforward but small issues can arise as command line arguments accepted by csc and features are not identical to mcs. For example, csc generates Portable PDB (.pdb) debug files instead of Mono’s MDB (.mdb) format. It also can’t do full signing on non-Windows platforms, use the /publicsign switch instead or use delay signing and sign the assembly with the sn tool after the build.

C# 7 adds a number of new features to the C# language:

  • out variables:
    • You can declare out values inline as arguments to the method where they are used.
  • Tuples
    • You can create lightweight, unnamed types that contain multiple public fields. Compilers and IDE tools understand the semantics of these types.
  • Pattern Matching
    • You can create branching logic based on arbitrary types and values of the members of those types.
  • ref locals and returns
    • Method arguments and local variables can be references to other storage.
  • Local Functions
    • You can nest functions inside other functions to limit their scope and visibility.
  • More expression-bodied members
    • The list of members that can be authored using expressions has grown.
  • throw Expressions
    • You can throw exceptions in code constructs that previously were not allowed because throw was a statement.
  • Generalized async return types
    • Methods declared with the async modifier can return other types in addition to Task and Task<T>.
  • Numeric literal syntax improvements
    • New tokens improve readability for numeric constants.

The new features in C# 7 can also be explored interactively as a Xamarin Workbook.


The Mono C# compiler is still available but it has not been updated to include C#7 features. The compiler is still maintained and all reported bugs have been fixed.


Over the past year we have been working to integrate the open-sourced msbuild build tool into Mono. It is now available as part of your Mono installation, and it is the same MSBuild that is used on .NET on Windows.

This resolves numerous incompatibilities we had in our previous xbuild implementation.


Mono’s historical implementation of MSBuild called xbuild is now deprecated. We encourage everyone to switch to the msbuild command which is now available on Mono as well.

Reference assemblies

The reference assemblies were updated to fully match the .NET 4.6.2 API set. This means that you no longer get compilation errors about missing classes/methods when building against one of the .NET profiles via msbuild/xbuild.

Note that at runtime certain APIs that Mono doesn’t (yet) implement will still throw an exception.



The pdb2mdb tool was updated so it no longer crashes when run against an assembly that has a Portable PDB debug symbols available.


The csharp REPL and scripting tool, which is based on the mcs compiler, now supports script-and-REPL-specific command line arguments, which are delimited by either the -s or -- arguments. These arguments are further made available in the Args global for easy processing in scripts.

It is now possible to write self-executing scripts with simple and unambiguous access to command line arguments:

#!/usr/bin/env csharp -s



Deprecation of Mono-bundled version of NUnit:

Mono used to ship with a forked copy of NUnit 2.4 that we used for testing Mono itself. For historical reasons it was never updated and is ancient at this point (it was released nearly 10 years ago!).

We moved to NUnitLite for testing Mono so we decided to deprecate the version we ship.

The nunit-console command will print a warning now. Compiling new projects against the NUnit DLLs from GAC will fail with an error message (existing test assemblies continue to work).

We recommend that you use a recent version of NUnit from NuGet or the project’s website instead.

CoreFX + Reference Source Adoption

As we announced we are adopting a new strategy to share code with .NET. With this release we started this effort where the code is shared between .NET Core and Mono and not just the Reference Source release.


The build system was fixed so it works without setting the git config --global core.autocrlf input setting which makes building Mono on Windows easier.


AppleTLS stack

The Mono.framework package that we distribute for macOS now uses the AppleTLS stack for implementing our SSL/TLS transport. This brings full support for TLS 1.2 for SslStream and our various HTTP web clients.

In the initial preview release, AppleTLS has two known issues:

  • Under certain circumstances, programs using AppleTLS may halt and present a GUI dialog requesting keychain access. More information and bugzilla entry here.
  • SecCertificateCreateWithData, and thus many X.509 functions, currently behave differently when given an invalid certificate on each of 10.9, 10.11, and 10.12. Bugzilla entry here.

We do offer a way of using the old SSL/TLS stack. Set the MONO_TLS_PROVIDER environment variable to legacy to use the old Mono managed TLS 1.0 stack. From your shell, you can do it like this:

export MONO_TLS_PROVIDER=legacy

libjpeg Update in macOS Package

The macOS SDK package now contains an updated libjpeg library that resolves the issue described in CVE-2013-6629. Our Mono distribution for macOS now includes an updated libjpeg.


SIMD Acceleration support

Generating SIMD accelerated native code for the classes in the Mono.Simd assembly is deprecated in this release, and it will be removed in +2 releases. Users should transition to using the Vector classes, which are part of the official .NET class libraries.

Environment Memory Management And System.Configuration

As per the Unix specification, getenv may return a pointer into static memory. Future calls to getenv can overwrite the memory returned from previous calls to getenv. Mono kept many pointers into this memory while concurrently calling getenv on multiple threads. We now lock around the environment-changing functions and to duplicate all returned strings.

Unfortunately, Mono will use the environment to find which configuration file to read for System.Configuration. Configurations that were set might not have been used, as managed code was seeing nulls. This is how the bug surfaced, it is not hypothetical. Users who set a custom configuration file (via MONO_CFG_DIR) are encouraged to check that using previously-ignored configuration files does not lead to unexpected breakage.

Match semantics of rethrow instruction with .NET runtime

Mono used to cut off the stack trace at the point where an exception is re-thrown, however, it should retain the stack trace if rethrow is used.

Experimental runtime interpreter

We revived the interpreter back from the old days (aka. mint). It now supports generics, and was updated to match internal API changes. It is disabled by default and shouldn’t be used in production yet.

The interpreter will be an execution option to the current runtime.

Clean-ups around native crashes

Native crashes now end up a single handler mono_handle_native_crash, that tries to provide as much information as possible. Also, SIGILL won’t get wrapped into a managed exception anymore but results into a native crash.

Internal Documentation

We have enabled Doxygen for documentation of runtime internals. Going forward, this should help us onboard new contributors and make the codebase easier to navigate and understand.

Lazy array interfaces

One curious aspect of C# is that arrays implement invariant interfaces as if they were covariant. This happens for IList<T>, ICollection<T> and IEnumerable<T> which means, for example, that string[] implements both IList<string> and IList<object>.

Mono traditionally implemented this by creating the runtime-side metadata for all of those interfaces and that came with an extraordinary memory cost of creating a lot of interfaces that never ended up being referenced by C# code.

With Mono 5.0 we now treat those interfaces as magic/special and use a different casting code-path. This allows them to be lazily implemented in arrays, which can save a lot of memory in LINQ-heavy workloads. As part of this work we refactored the casting code in the JIT to be simpler and more maintainable.

Memory usage

Improvements in the runtime representation of the type system should yield a 5% memory saving in most workloads. It was achieved by using a more efficient representation for arrays and generic instances.

A linearizable property bag was added to replace the current mechanism of rare fields in runtime metadata. More rarely used fields were moved to use it as they now use significantly less memory when used.

SGen Improvements

As of this release we are enabling concurrent SGen as the default mode on desktop platforms. This mode significantly reduces the time spent in major collections, by doing most of the work concurrently with the application. In order to use the old serial collector you can pass to the environment MONO_GC_PARAMS=major=marksweep.

A new parallel SGen mode has been added for majors. This mode uses multiple workers in order to finish a concurrent collection and it is currently experimental. If you are still experiencing large pauses with the concurrent collector, you can try out the parallel mode by passing MONO_GC_PARAMS=major=marksweep-conc-par.

SGen uses an optimized custom implementation of quicksort to improve the performance of some GC operations. Previously, it selected a poor choice of pivot, which could lead to worst-case time complexity in some circumstances. It has been rewritten with an improved pivot strategy.

This release includes some performance improvements in ephemeron processing, which also translate to shorter collections. Ephemerons are an internal structure used by the SGen to implement the semantics of ConditionalWeakTable. This also includes a fix for a long-standing leak when using and disposing of a lot of these structures.

Major block allocation and freeing was tweaked in order to reduce fragmentation of the virtual memory space.

SIMD Register Scanning

Certain compiler optimizations can lead to object references being stored in SIMD registers, for example, during an optimized copy of an array of references. Previously, the runtime did not scan these registers, which could cause objects to be prematurely freed if the garbage collector happened to run while the only reference to an object resided in such a register. The runtime now correctly scans these registers for object references during garbage collection.

Static Analysis

We are investing in static analysis of the runtime to verify our use of locks, signals, and global state. This should help reduce concurrency errors, improving correctness and stability. As a first step, we have already caught some locking errors in the garbage collector.


The runtime crash stack traces now include information on managed stack traces to allow them to be symbolificated. Tooling was adjusted to handle the slightly different format.

Thread.Abort hardening

The runtime was hardened to further its resilience in face of thread aborts. It now won’t abort in-flight class constructors. Thread abort is important for application using multiple AppDomains.


ThreadAbortException remains set during stack unwinding unless manually unset. While inside of a function call inside of a catch block for the exception, it was possible for us to see the set ThreadAbortException and behave as if the call inside of the catch block threw it. This has been fixed.

Unwinding on Android

On a native crash on Android, the Mono runtime tried to dlopen libcorkscrew or libunwind (depending on what is available) in order to obtain a native stack trace. However, this approach was unreliable, as some devices don’t even ship said libraries. Furthermore, Android will restrict the dlopen syscall in an unfavorable way for this approach in a future version.

We changed our approach by trying to do less work: We now rely on a system process by Android aka. debuggerd to provide us a native stack trace. On some Android versions this requires us to set DUMPABLE.

Workaround for .NET Standard NuGets on desktop

Some .NET Standard NuGets like System.IO.Compression resolve to assemblies that won’t work with Mono on Desktop. To handle this we implemented a series of workarounds:

  • Deny loading problematic assemblies. They will be handled as if they did not exist
  • Deny remapping to problematic assembly versions. The system version will be used instead.

Windows Support

Mono can now run on Win64.

Bring PowerPC back to life

Mono can bootstrap on ppc64le.

Bug Fixes

/placeholder for list of fixed bugzilla bugs/


/placeholder for list of contributors/