Skip to content

where T unmanaged (no references)

Context: The unmanaged constraint (available since C# 7.3) requires the type parameter to be an unmanaged type: a value type that contains no references to managed objects (no reference-type fields). This includes primitive types, enums, and structs composed only of unmanaged fields. This constraint is useful for interop with unmanaged code (P/Invoke, stack allocations, etc.).

using System;
using System.Runtime.InteropServices;
public struct UnmanagedPoint
{
public int X;
public int Y;
// No reference fields
}
public struct PointWithReference
{
public int X;
public string Description; // reference -> not allowed
}
public class UnmanagedBuffer<T> where T : unmanaged
{
public unsafe T* Allocate(int count)
{
return (T*)Marshal.AllocHGlobal(count * sizeof(T));
}
}
class Program
{
static void Main()
{
var buffer = new UnmanagedBuffer<UnmanagedPoint>();
Console.WriteLine("Unmanaged buffer created (simulated)");
// This does not compile: PointWithReference contains a reference
// var errorBuffer = new UnmanagedBuffer<PointWithReference>();
}
}
Terminal window
dotnet run
Unmanaged buffer created (simulated)
  • unmanaged types are a subset of struct.
  • Allows using sizeof(T) and stackalloc T[].
  • Ideal for high-performance APIs or interop.

System.Span<T> – Uses unmanaged constraints internally for some optimizations.
See .NET docs on unmanaged constraint.