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;
}
}
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.
- Identify the Goal: Does the method need to read the variable you are passing in?
- Yes: Use
ref(notout). - No: Use
out, but remove the[In]attribute.
- Yes: Use
- Check Attributes: Ensure you aren't copy-pasting C++ interface definitions (
[In]) onto C#outparameters.