How to Resolve Error "CS0835: Cannot convert lambda to an expression tree whose type argument 'type' is not a delegate type" in C#
The Compiler Error CS0835 is a type mismatch error regarding Expression Trees. The message reads: "Cannot convert lambda to an expression tree whose type argument 'int' (or other type) is not a delegate type."
In C#, an Expression Tree (Expression<T>) is a data structure that represents logic. Because it represents code logic (inputs and outputs), the type argument T must be a Delegate (like Func<...>, Action<...>, or a custom delegate). You cannot create an Expression<int> or Expression<string> using a lambda, because int and string are data types, not function signatures.
This guide explains how to correctly define the type arguments for Expression Trees.
Understanding Expression Tree Types
When you write a lambda expression x => x + 1, it represents a function.
- To store it as executable code, you use a Delegate:
Func<int, int>. - To store it as a data structure (Expression Tree), you wrap that Delegate:
Expression<Func<int, int>>.
The generic argument inside <...> tells the compiler what kind of function is being represented. If you put a non-delegate type there, the compiler doesn't know how to map the lambda syntax to that type.
Scenario 1: Declaring Expression of Data Types
This is the most common mistake. You want an expression that returns an integer, so you declare it as Expression<int>. However, Expression<T> expects T to be the function signature, not the return type.
Example of error
Attempting to create an expression using int as the generic argument.
using System;
using System.Linq.Expressions;
public class Program
{
static void Main()
{
// ⛔️ Error CS0835: Cannot convert lambda to an expression tree
// whose type argument 'int' is not a delegate type.
// The compiler sees "() => 5", which is a function.
// But 'int' is just a number, not a function signature.
Expression<int> expression = () => 5;
}
}
Solution: Use Func or Action
Wrap the return type inside a Func<T>.
using System;
using System.Linq.Expressions;
public class Program
{
static void Main()
{
// ✅ Correct: 'Func<int>' is a delegate representing a method that returns int.
// The Expression now correctly wraps that delegate.
Expression<Func<int>> expression = () => 5;
// Compile and run
Console.WriteLine(expression.Compile().Invoke()); // Output: 5
}
}
If your lambda takes arguments (e.g., x => x > 5), use Expression<Func<int, bool>>. The type inside the brackets must always describe the full function signature.
Scenario 2: Generic Type Misalignment
This often occurs when creating generic helper methods. You define a method that accepts Expression<T>, but then you call it passing a T that is not a delegate (like an entity class or a primitive).
Example of error
Calling a generic method with an invalid type argument.
public class Repository
{
// This method expects T to be a Delegate type (though not constrained here)
public void AddRule<T>(Expression<T> rule)
{
}
}
public class Program
{
static void Main()
{
var repo = new Repository();
// ⛔️ Error CS0835: 'bool' is not a delegate type.
// We are trying to pass 'Expression<bool>', which is invalid.
repo.AddRule<bool>(() => true);
}
}
Solution: Adjust the Generic Definition
Usually, you want the expression to represent a predicate (a function taking an entity and returning bool) or a specific function. Adjust the method signature to wrap T in Func.
public class User { }
public class Repository
{
// ✅ Correct: We changed the parameter to Expression<Func<T, bool>>.
// Now 'T' represents the Entity (User), not the Delegate itself.
public void AddRule<T>(Expression<Func<T, bool>> rule)
{
}
}
public class Program
{
static void Main()
{
var repo = new Repository();
// ✅ Correct: T is 'User'. The Expression is 'Func<User, bool>'.
repo.AddRule<User>(u => true);
}
}
Conclusion
CS0835 ensures that Expression Trees wrap logic, not raw data.
- Check the Type Argument: Look at
Expression<T>. IsTanint,string, orMyClass? - Wrap in Delegate: Change
Tto a delegate type likeFunc<T>(if returning a value) orAction<T>(if void). - Check Generics: If using generic methods, ensure the parameter is defined as
Expression<Func<T>>rather than justExpression<T>ifTis meant to be the data model.