How to Resolve Error "CS0765: Partial methods with only a defining declaration or removed conditional methods cannot be used in expression trees" in C#
The Compiler Error CS0765 is a restriction related to Expression Trees (Expression<T>). The message reads: "Partial methods with only a defining declaration or removed conditional methods cannot be used in expression trees".
In C#, an Expression Tree represents code as data structures. To build this tree, every node (method call, property access, binary operation) must point to a valid, existing member with metadata.
However, Partial Methods without an implementation and methods marked with [Conditional] (where the condition is not met) are effectively removed by the compiler. If you try to reference such a "ghost" method inside an Expression Tree, the compiler cannot build the tree because the method call technically does not exist in the final assembly.
This guide explains how to work around this limitation using wrapper methods or by ensuring the method exists.
Understanding the "Ghost Method" Problem
When you compile code, the C# compiler performs optimizations:
- Partial Methods: If
partial void OnChange();has no implementation body in any file, all calls toOnChange()are deleted from the IL (Intermediate Language). - Conditional Methods: If
[Conditional("DEBUG")] void Log()is called in aRELEASEbuild, the call is deleted.
Expression Trees require a MethodInfo object to construct a MethodCallExpression. You cannot get MethodInfo for a method that the compiler decided to delete.
Scenario 1: Unimplemented Partial Methods
This usually happens when you are using a library like Entity Framework or LINQ, and you try to use a partial method inside a lambda expression passed to a method expecting Expression<Action>.
Example of error
using System;
using System.Linq.Expressions;
public partial class User
{
// A defining declaration (No body yet)
partial void OnNameChanged();
public void CreateExpression()
{
// ⛔️ Error CS0765: The compiler cannot build an expression tree
// for 'OnNameChanged' because it might be removed during compilation.
Expression<Action> expr = () => OnNameChanged();
}
}
Solution 1: Use a Wrapper Method (The Proxy Pattern)
If the partial method is optional (you might not implement it), you cannot put it directly in the expression tree. Instead, wrap the call inside a standard method. The Expression Tree will point to the Wrapper (which always exists), and the Wrapper will conditionally call the Partial Method (which might vanish).
public partial class User
{
partial void OnNameChanged();
// 1. Create a non-partial wrapper that always exists
private void OnNameChangedWrapper()
{
// Calling it here is standard code (not an expression tree),
// so the compiler can safely remove this line if needed.
OnNameChanged();
}
public void CreateExpression()
{
// 2. Point the Expression Tree to the Wrapper
// ✅ Correct: 'OnNameChangedWrapper' is a valid method metadata source.
Expression<Action> expr = () => OnNameChangedWrapper();
}
}
Solution 2: Implement the Partial Method
If you implement the partial method, it becomes a real method in the compiled assembly. However, standard partial methods are implicitly private, so this only fixes the error if you implement it.
Note: In C# 9.0+, if you make it an Extended Partial Method (by adding an access modifier like private), implementation becomes mandatory, and the method is never removed. This also fixes the error.
public partial class User
{
// ✅ Correct: Adding 'private' forces implementation and prevents removal.
private partial void OnNameChanged();
public void CreateExpression()
{
// Now valid because the method is guaranteed to exist
Expression<Action> expr = () => OnNameChanged();
}
}
public partial class User
{
private partial void OnNameChanged() { /* ... */ }
}
Scenario 2: Conditional Methods ([Conditional])
Methods decorated with [Conditional("SYMBOL")] are only compiled if that symbol is defined. If you use such a method in an Expression Tree while the symbol is not defined (e.g., a DEBUG method in RELEASE mode), CS0765 occurs.
Example of error
using System.Diagnostics;
using System.Linq.Expressions;
using System;
public class Logger
{
[Conditional("DEBUG")]
public void LogDebug(string msg)
{
Console.WriteLine(msg);
}
public void Run()
{
// ⛔️ Error CS0765 (In RELEASE build): 'LogDebug' is removed,
// so it cannot be part of the expression tree.
Expression<Action> expr = () => LogDebug("Test");
}
}
Solution: Wrap in a Standard Method
Just like with partial methods, wrap the conditional logic inside a standard method. The Expression Tree will call the wrapper. The wrapper will be empty in Release mode (because the call inside it is removed), but the wrapper method itself still exists.
public class Logger
{
[Conditional("DEBUG")]
public void LogDebug(string msg) { /*...*/ }
// ✅ Correct: The wrapper always exists.
public void SafeLog(string msg)
{
LogDebug(msg);
}
public void Run()
{
// The Expression Tree targets 'SafeLog'
Expression<Action> expr = () => SafeLog("Test");
}
}
Conclusion
CS0765 prevents you from building data structures based on code that doesn't exist.
- Understand the Constraint: Expression Trees need Method Metadata (
MethodInfo). - Identify the Cause: Are you pointing to a
partial voidwith no body? Or a[Conditional]method that is currently disabled? - The Fix: Use a Wrapper Method. Define a standard
void Method()that calls the problematic method, and put the Wrapper inside the Expression Tree.