Skip to main content

How to Resolve Error "CS0036: An out parameter cannot have the In attribute" in C#

The Compiler Error CS0036 is a logic contradiction error. The message states: "An out parameter cannot have the In attribute".

This error occurs typically when working with Interop (referencing C++ DLLs or COM objects) using the System.Runtime.InteropServices namespace. It happens because you have combined two mutually exclusive instructions: the C# keyword out (which means data flows only out) and the marshalling attribute [In] (which means data flows in from the caller).

This guide explains why these two concepts conflict and how to define your method signatures correctly.

Understanding the Conflict

To the C# compiler and the .NET Runtime, these two terms define the direction of data flow:

  • out (Keyword): The variable is uninitialized going in. The method must assign a value to it before returning. The flow is strictly Callee -> Caller.
  • [In] (Attribute): Tells the Marshaller to copy data from the Caller to the Callee. The flow is Caller -> Callee.

You cannot have a parameter that is strictly "Result Only" (out) but also marked as "Input Required" ([In]).

Scenario: The Invalid Combination

This usually appears when writing P/Invoke signatures for external DLLs.

Example:

using System.Runtime.InteropServices;

public class NativeWrapper
{
// ⛔️ Error CS0036: An out parameter cannot have the In attribute
// You are telling the compiler: "This variable is output only,"
// but telling the runtime: "Please marshal input data into this variable."
public static void GetData([In] out int value)
{
value = 10;
}
}

Solution 1: Remove the [In] Attribute (Pure Output)

If your intention is to return a value from the method (which is what out implies), you should remove the [In] attribute. You may optionally use [Out], though it is usually redundant for out parameters.

using System.Runtime.InteropServices;

public class NativeWrapper
{
// ✅ Correct: 'out' implies [Out]. No input data is sent.
public static void GetData(out int value)
{
value = 10;
}

// ✅ Correct: Explicitly stating [Out] is allowed (but redundant)
public static void GetDataExplicit([Out] out int value)
{
value = 20;
}
}

Solution 2: Switch to 'ref' (Bidirectional)

If you are wrapping a C++ function that takes a pointer, reads the value, modifies it, and sends it back (Input and Output), you cannot use out. You must use ref.

The ref keyword supports both [In] and [Out] attributes because the variable is initialized before the call.

using System.Runtime.InteropServices;

public class NativeWrapper
{
// ✅ Correct: 'ref' allows data to flow In and Out.
// Using [In, Out] is valid here.
public static void ModifyData([In, Out] ref int value)
{
// We can read the input value
System.Console.WriteLine($"Input was: {value}");

// And write the output value
value = 50;
}
}
note

Summary of Marshalling Directions:

  • out int x = Pure Output. (Implicitly [Out])
  • ref int x = Input and Output. (Implicitly [In, Out])
  • int x = Pure Input. (Implicitly [In])

Conclusion

CS0036 enforces logical consistency in method signatures.

  1. Identify the Goal: Does the method need to read the variable you are passing in?
    • Yes: Use ref (not out).
    • No: Use out, but remove the [In] attribute.
  2. Check Attributes: Ensure you aren't copy-pasting C++ interface definitions ([In]) onto C# out parameters.