Skip to content

Instantly share code, notes, and snippets.

@fredeil
Created July 19, 2018 07:01
Show Gist options
  • Save fredeil/a14597f5b6d5f95ade4d0e8ea47ef8ee to your computer and use it in GitHub Desktop.
Save fredeil/a14597f5b6d5f95ade4d0e8ea47ef8ee to your computer and use it in GitHub Desktop.
The unmanaged constraint in C# 7.3

The unmanaged constraint

The unmanaged constraint on generic type T enforces the type to be an 'unmanaged' struct that does not recursively contain reference type fields. The concept of 'unmanaged types' existed in the C# language for a long time and you can find this term in the C# language specification and in the official documentation, but now the compiler can actually enforce it.

This feature could be useful for low-level scenarios, like native-managed interoperability, but could be helpful for common enterprise scenarios as well. An instance of 'unmanaged' type T is convertible to T* which is convertible to byte* that opens some interesting possibilities. Let suppose you want to keep your data in a key-value store. To get a key you may consider using SHA1 or some other hashing algorithm, but you don't want to implement the hashing logic for every type in the system.

This code works perfectly fine because sizeof operator is actually designed for 'unmanaged' types even though there was no special constraint in the language to enforce the correctness of this operator at compile time.

public unsafe static byte[] ComputeHash<T>(T data) where T : unmanaged
{
byte* bytes = (byte*)(&data);
using (var sha1 = SHA1.Create())
{
var size = sizeof(T);
using (var ms = new UnmanagedMemoryStream(bytes, size))
{
return sha1.ComputeHash(ms);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment