Skip to main content

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 to OnChange() are deleted from the IL (Intermediate Language).
  • Conditional Methods: If [Conditional("DEBUG")] void Log() is called in a RELEASE build, 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.

  1. Understand the Constraint: Expression Trees need Method Metadata (MethodInfo).
  2. Identify the Cause: Are you pointing to a partial void with no body? Or a [Conditional] method that is currently disabled?
  3. The Fix: Use a Wrapper Method. Define a standard void Method() that calls the problematic method, and put the Wrapper inside the Expression Tree.