How to Resolve Error "CS0636: The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)" in C#
The Compiler Error CS0636 is an attribute configuration error related to Interop and memory layout. The message reads: "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)".
In C#, the compiler usually decides how to arrange fields in memory (Automatic layout) or arranges them in the order they are defined (Sequential layout). The [FieldOffset] attribute allows you to manually specify the exact byte offset of a field, effectively enabling you to create Unions (where fields overlap in memory) or map to complex C/C++ structures.
However, specifying an offset is meaningless unless the structure itself is configured to accept manual layout instructions. This error occurs when you use [FieldOffset] but forget to declare the struct as Explicit.
Understanding Struct Layouts
The System.Runtime.InteropServices.StructLayoutAttribute controls how data fields are arranged in unmanaged memory.
LayoutKind.Auto(Default for Classes): The runtime rearranges fields for efficiency.FieldOffsetis forbidden.LayoutKind.Sequential(Default for Structs): Fields are laid out in order of declaration.FieldOffsetis forbidden because the order is already fixed.LayoutKind.Explicit: You are the boss. You must tell the runtime exactly where every byte goes usingFieldOffset.
CS0636 happens when you try to be the boss (using FieldOffset) without declaring your authority (LayoutKind.Explicit).
Scenario 1: Missing the Layout Attribute
The most common cause is defining a struct intended to be a Union but forgetting the main attribute on the type definition.
Example of error:
using System.Runtime.InteropServices;
public struct UnionData
{
// ⛔️ Error CS0636: The FieldOffset attribute can only be placed on members...
// By default, a struct is LayoutKind.Sequential.
// You cannot manually offset fields in a Sequential layout.
[FieldOffset(0)]
public int IntegerVal;
[FieldOffset(0)]
public float FloatVal;
}
Scenario 2: Incorrect LayoutKind (Sequential/Auto)
Even if you add the StructLayout attribute, selecting Sequential or Auto will still trigger this error. FieldOffset implies absolute positioning, which conflicts with the logic of relative positioning used by Sequential/Auto.
Example of error:
using System.Runtime.InteropServices;
// ⛔️ Error: Sequential layout does not support FieldOffset.
[StructLayout(LayoutKind.Sequential)]
public struct Packet
{
[FieldOffset(4)] // CS0636
public int Id;
}
Solution: Use LayoutKind.Explicit
To fix this, you must explicitly mark the struct (or class) with [StructLayout(LayoutKind.Explicit)]. This tells the compiler: "I will provide the offsets for every single field manually."
Solution 1: Create a Union
This example creates a C-style Union where an integer and a float share the same memory space.
using System.Runtime.InteropServices;
// ✅ Correct: Explicit layout enables the use of FieldOffset
[StructLayout(LayoutKind.Explicit)]
public struct UnionData
{
// Both fields start at byte 0, so they overlap.
[FieldOffset(0)]
public int IntegerVal;
[FieldOffset(0)]
public float FloatVal;
}
Solution 2: Simulate C structs with gaps
You can also use this to create gaps in memory (padding) manually.
[StructLayout(LayoutKind.Explicit)]
public struct SparseData
{
[FieldOffset(0)]
public byte StartByte;
// Skip 3 bytes of padding manually
[FieldOffset(4)]
public int Data;
}
Conclusion
CS0636 ensures you don't send conflicting instructions to the memory layout engine.
- Check the Attribute: Do you have
[FieldOffset(...)]on a field? - Check the Parent: Does the enclosing
structorclasshave[StructLayout(LayoutKind.Explicit)]? - The Rule: You cannot use
FieldOffsetwithoutLayoutKind.Explicit.