Unmanaged types (C# reference)

A type is an unmanaged type if it's any of the following types:

  • sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool
  • Any enum type
  • Any pointer type
  • Any user-defined struct type that contains fields of unmanaged types only and, in C# 7.3 and earlier, is not a constructed type (a type that includes at least one type argument)

Beginning with C# 7.3, you can use the unmanaged constraint to specify that a type parameter is a non-pointer unmanaged type.

Beginning with C# 8.0, a constructed struct type that contains fields of unmanaged types only is also unmanaged, as the following example shows:

using System;

public struct Coords<T>
{
    public T X;
    public T Y;
}

public class UnmanagedTypes
{
    public static void Main()
    {
        DisplaySize<Coords<int>>();
        DisplaySize<Coords<double>>();
    }

    private unsafe static void DisplaySize<T>() where T : unmanaged
    {
        Console.WriteLine($"{typeof(T)} is unmanaged and its size is {sizeof(T)} bytes");
    }
}
// Output:
// Coords`1[System.Int32] is unmanaged and its size is 8 bytes
// Coords`1[System.Double] is unmanaged and its size is 16 bytes

A generic struct may be the source of both unmanaged and not unmanaged constructed types. The preceding example defines a generic struct Coords<T> and presents the examples of unmanaged constructed types. The example of not an unmanaged type is Coords<object>. It's not unmanaged because it has the fields of the object type, which is not unmanaged. If you want all constructed types to be unmanaged types, use the unmanaged constraint in the definition of a generic struct:

public struct Coords<T> where T : unmanaged
{
    public T X;
    public T Y;
}

C# language specification

For more information, see the Pointer types section of the C# language specification.

See also