How to Resolve Error "CS0854: An expression tree may not contain a call or invocation that uses optional arguments" in C#
The Compiler Error CS0854 is a limitation of the C# Expression Tree system. The message reads: "An expression tree may not contain a call or invocation that uses optional arguments".
In standard C#, when you call a method that has optional parameters (e.g., void Method(int a = 5)), you can omit the argument, and the compiler automatically inserts the default value (5) into the compiled code. However, Expression Trees (Expression<Func<...>>) represent code as a data structure. The compiler restricts this "automatic insertion" logic inside Expression Trees to ensure the data structure remains explicit and unambiguous for query providers (like Entity Framework).
This guide explains how to make your method calls explicit to satisfy the Expression Tree requirements.
Understanding the Limitation
- Standard Call:
MyMethod();-> Compiler rewrites toMyMethod(10);(if 10 is default). - Expression Tree: The compiler generates nodes representing the syntax. It refuses to silently modify the syntax tree to inject arguments you didn't type. It demands that the tree exactly matches the provided source code, but the underlying method signature requires an argument that is missing in the source.
To fix this, you must stop relying on the compiler to fill in the blanks and provide the arguments yourself.
Scenario 1: Calling Methods with Default Values
This is the most common occurrence. You are defining an expression (perhaps for a LINQ query or a configuration lambda) and calling a helper method that has optional parameters.
Example of error
You omit the argument, expecting the default value to apply.
using System;
using System.Linq.Expressions;
public class Logger
{
// Method with an optional parameter
public void Log(string message, int severity = 1)
{
Console.WriteLine($"[{severity}] {message}");
}
}
public class Program
{
static void Main()
{
Logger logger = new Logger();
// ⛔️ Error CS0854: An expression tree may not contain a call
// or invocation that uses optional arguments.
// The compiler refuses to inject '1' for the 'severity' parameter automatically.
Expression<Action> expr = () => logger.Log("System Start");
}
}
Solution: Provide the Argument Explicitly
You must manually pass the default value (or any specific value) so that the call site matches the method signature exactly.
using System;
using System.Linq.Expressions;
public class Logger
{
public void Log(string message, int severity = 1)
{
Console.WriteLine($"[{severity}] {message}");
}
}
public class Program
{
static void Main()
{
Logger logger = new Logger();
// ✅ Correct: We explicitly pass '1' (the default value).
// The expression tree now has a clear argument for every parameter.
Expression<Action> expr = () => logger.Log("System Start", 1);
expr.Compile().Invoke();
}
}
Output:
[1] System Start
If the default value might change in the future and you don't want to hardcode 1, you cannot easily reference the "default defined in the method signature" inside an expression. You would have to define a constant public const int DefaultSeverity = 1; and use that constant in both the method signature and the expression.
Scenario 2: Constructors with Optional Parameters
This error also applies to object instantiation (new) inside LINQ projections if the constructor uses optional parameters.
Example of error
Trying to create a new object in an IQueryable projection while skipping constructor arguments.
using System;
using System.Linq;
using System.Linq.Expressions;
public class UserViewModel
{
public string Name { get; set; }
// Constructor with optional parameter
public UserViewModel(string name, bool isActive = true)
{
Name = name;
}
}
public class Program
{
static void Main()
{
// ⛔️ Error CS0854: Cannot use optional argument 'isActive' inside Expression.
Expression<Func<string, UserViewModel>> create =
name => new UserViewModel(name);
}
}
Solution: Pass All Arguments
Supply the values for every parameter defined in the constructor.
using System;
using System.Linq.Expressions;
public class UserViewModel
{
public string Name { get; set; }
public UserViewModel(string name, bool isActive = true) { Name = name; }
}
public class Program
{
static void Main()
{
// ✅ Correct: We explicitly pass 'true'.
Expression<Func<string, UserViewModel>> create =
name => new UserViewModel(name, true);
}
}
Conclusion
CS0854 enforces explicit definitions within Expression Trees.
- Identify the Method: Find the method call inside your lambda
() => .... - Check Parameters: Does that method have parameters with
= valuedefaults? - Fill the Blanks: You cannot skip them. Pass the values explicitly.