Skip to content

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

Fix the CS0226 compiler error when using __arglist in C# by understanding its restricted syntax, only valid inside method calls for P/Invoke with unmanaged code like 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)).
Navigation