Skip to main content

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
}
}
note

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.

  1. Check the Type Argument: Look at Expression<T>. Is T an int, string, or MyClass?
  2. Wrap in Delegate: Change T to a delegate type like Func<T> (if returning a value) or Action<T> (if void).
  3. Check Generics: If using generic methods, ensure the parameter is defined as Expression<Func<T>> rather than just Expression<T> if T is meant to be the data model.