Skip to main content

How to Resolve Error "CS0226: An '__arglist' expression may only appear inside of a call or new expression" in C#

The Compiler Error CS0226 is a syntax error related to the undocumented legacy keyword __arglist. The message reads: "An __arglist expression may only appear inside of a call or new expression".

The __arglist keyword provides access to the C-style variable argument lists (varargs), primarily for Interoperability (P/Invoke) with unmanaged code like C++ methods. Because it interacts directly with the calling convention of a method, it is only valid inside the parentheses of a method invocation or a constructor call. You cannot use it as a standalone variable, return value, or in other expressions.

This guide explains how to correctly use this rare feature when interacting with unmanaged libraries.

Understanding __arglist

In standard C#, we use the params keyword for variable arguments. However, params creates a C# array. C-style functions (like printf in msvcrt.dll) do not understand C# arrays; they expect arguments pushed onto the stack in a specific way.

  • Definition: void MyMethod(__arglist) indicates the method accepts varargs.
  • Usage: MyMethod(__arglist(x, y, z)) indicates you are passing varargs.

The syntax __arglist(...) constructs a special RuntimeArgumentHandle. This construction is only valid at the exact moment of calling the function.

Scenario: Incorrect Usage of __arglist

This error occurs when you try to treat the result of __arglist(...) as if it were a regular object or variable that can be stored.

Example of Trying to assign the argument list to a variable before passing it.

public class Interop
{
// Method defined to accept __arglist
public static void NativeLog(__arglist)
{
}

public static void Run()
{
int x = 5;
int y = 10;

// ⛔️ Error CS0226: An __arglist expression may only appear
// inside of a call or new expression.
// You cannot "save" the arglist creation to a variable.
var args = __arglist(x, y);

NativeLog(args); // This would be invalid
}
}

Solution: Moving __arglist into the Call

You must inline the __arglist expression directly into the method call parentheses.

Solution

public class Interop
{
public static void NativeLog(__arglist)
{
// Implementation usually involves ArgIterator
ArgIterator iterator = new ArgIterator(__arglist);
}

public static void Run()
{
int x = 5;
int y = 10;

// ✅ Correct: __arglist is used directly inside the function call
NativeLog(__arglist(x, y));
}
}

Example: Calling printf (P/Invoke)

The most common real-world use case is calling standard C library functions.

using System.Runtime.InteropServices;

class Program
{
// Define the extern method with __arglist
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int printf(string format, __arglist);

static void Main()
{
// ✅ Correct usage
printf("Val: %d, Str: %s\n", __arglist(123, "Hello"));
}
}

Conclusion

CS0226 enforces the transient nature of the __arglist structure.

  1. Usage Restriction: You cannot assign __arglist(...) to a variable (var x = ...).
  2. Usage Restriction: You cannot return __arglist(...) from a method.
  3. Correct Syntax: Always type it directly inside the call: Method(__arglist(a, b)).