Skip to main content

How to Resolve Error "CS0635: System.Interop.UnmanagedType.CustomMarshaler requires named arguments MarshalType and MarshalCookie" in C#

The Compiler Error CS0635 is a configuration error related to Interop (interoperability with unmanaged code). The message reads: "'Attribute' : System.Runtime.InteropServices.UnmanagedType.CustomMarshaler requires named arguments MarshalType and MarshalCookie".

note

The exact error message usually asks for MarshalType, MarshalTypeRef, or MarshalCookie, though older documentation might refer to ComType.

When you use the [MarshalAs(UnmanagedType.CustomMarshaler)] attribute, you are telling the CLR: "I have written a custom class to handle the conversion of this specific parameter." However, simply saying "Use a custom marshaler" is not enough. You must explicitly tell the CLR which class to use as the marshaler and (optionally) provide a "cookie" string to configure it. Without these named arguments, the attribute is incomplete.

Understanding Custom Marshaling​

Standard marshaling handles common types (e.g., converting string to LPStr). Custom marshaling allows you to write a class that implements ICustomMarshaler to handle complex or non-standard conversions between .NET (Managed) and C++ (Unmanaged) memory.

To wire this up, you apply the attribute to a field or parameter: [MarshalAs(UnmanagedType.CustomMarshaler)]

This declaration is logically incomplete without answering the question: "Which Custom Marshaler?"

Scenario: The Incomplete Attribute​

This error occurs when you select UnmanagedType.CustomMarshaler but forget to provide the mandatory named properties that identify your custom class.

Example of error:

using System;
using System.Runtime.InteropServices;

public class NativeMethods
{
// ⛔️ Error CS0635: UnmanagedType.CustomMarshaler requires named arguments.
// The compiler doesn't know which class contains the marshaling logic.
[DllImport("MyLib.dll")]
public static extern void DoWork(
[MarshalAs(UnmanagedType.CustomMarshaler)] object data
);
}

Solution: Specify MarshalType or MarshalTypeRef​

You must provide one of the two identification properties:

  1. MarshalTypeRef: The System.Type of your custom marshaler class (Recommended, strongly typed).
  2. MarshalType: The fully qualified string name of the class (Error-prone due to typos).

Prerequisite: A Custom Marshaler Class​

First, ensure you have a class that implements ICustomMarshaler.

public class MyCustomMarshaler : ICustomMarshaler
{
// Singleton pattern is required for custom marshalers
private static MyCustomMarshaler _instance = new MyCustomMarshaler();
public static ICustomMarshaler GetInstance(string cookie) => _instance;

public object MarshalNativeToManaged(IntPtr pNativeData) => null;
public IntPtr MarshalManagedToNative(object ManagedObj) => IntPtr.Zero;
public void CleanUpNativeData(IntPtr pNativeData) { }
public void CleanUpManagedData(object ManagedObj) { }
public int GetNativeDataSize() => -1;
}

Solution: Linking the Class​

Now update the MarshalAs attribute to point to MyCustomMarshaler.

public class NativeMethods
{
[DllImport("MyLib.dll")]
public static extern void DoWork(
// ✅ Correct: We explicitly tell the CLR to use 'MyCustomMarshaler'
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MyCustomMarshaler))]
object data
);
}

Advanced: Using MarshalCookie​

The error message might also mention MarshalCookie (or Cookie in some contexts). While often optional, this is a string argument passed to your marshaler's GetInstance(string cookie) method. It allows you to reuse one marshaler logic for slightly different scenarios.

Even if you don't need a cookie, the error implies that the syntax structure for CustomMarshaler expects these named parameters.

public class NativeMethods
{
[DllImport("MyLib.dll")]
public static extern void DoWork(
[MarshalAs(UnmanagedType.CustomMarshaler,
MarshalTypeRef = typeof(MyCustomMarshaler),
MarshalCookie = "SpecialMode")] // Passed to GetInstance()
object data
);
}

Conclusion​

CS0635 is a missing configuration error.

  1. Check the Type: Did you use UnmanagedType.CustomMarshaler?
  2. Provide the Link: You must add , MarshalTypeRef = typeof(MyClass) inside the attribute parentheses.
  3. Check the Class: Ensure the class you reference actually implements ICustomMarshaler.