dotnet/efcore · error · NotImplementedException
Switch with non-null comparison method
Error message
Switch with non-null comparison method
What it means
Thrown by TranslateSwitch when a LINQ System.Linq.Expressions.SwitchExpression has a non-null Comparison property. C# switch expressions have no equivalent comparison-method concept (they use pattern matching equality), so the translator cannot faithfully represent a custom comparer and throws NotImplementedException rather than silently dropping it.
Solutions
- Avoid SwitchExpression overloads that set a custom Comparison when the tree will be translated to C#.
- Rewrite the switch to use default equality matching so Comparison stays null.
- Move the custom-comparison switch logic out of the translated expression tree into a separately callable method.
Example fix
// before Expression.Switch(value, comparer: myComparer, cases...); // after Expression.Switch(value, cases...); // omit the comparison argument
Defensive patterns
Strategy: validation
Validate before calling
// Reject switch expressions carrying a comparison before translating
static bool HasCustomComparison(Expression e)
{
bool found = false;
new SwitchChecker { Found = () => found = true }.Visit(e);
return found;
}
class SwitchChecker : ExpressionVisitor
{
public Action Found;
protected override Expression VisitSwitch(SwitchExpression node)
{
if (node.Comparison is not null) Found();
return base.VisitSwitch(node);
}
} Type guard
static bool IsTranslatableSwitch(SwitchExpression s) => s.Comparison is null;
Try / catch
try { var csharp = translator.Translate(expr); }
catch (NotImplementedException ex) when (ex.Message.Contains("Switch with non-null comparison"))
{ throw new InvalidOperationException("Custom-comparison switch expressions cannot be translated to C#.", ex); } Prevention
- Prefer the Expression.Switch overload without a comparison argument.
- Review programmatically built trees for SwitchExpression.Comparison.
- Move custom-equality logic out of the translated tree.
When it happens
Trigger: An expression tree contains a SwitchExpression whose Comparison was set to a non-null MethodInfo (e.g. constructed via Expression.Switch with a comparison argument), and that tree is translated to C# by the precompiled-query/compiled-model translator.
Common situations: Programmatic expression-tree construction using the SwitchExpression overload that takes a custom comparison; a query or value selector that the C# translator cannot round-trip because of a non-default equality comparer on a switch.
Related errors
- Missing default arm for switch expression
- Encountered non-quotable expression of type
- Unary node with non-null method
- Unnamed captured variable
- Unsupported LINQ unary node
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/10da0d465e62df00.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs:2199
/// <inheritdoc />
protected override Expression VisitSwitch(SwitchExpression switchNode)
{
Result = TranslateSwitch(switchNode, lowerableAssignmentVariable: null);
return switchNode;
}
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
protected virtual CSharpSyntaxNode TranslateSwitch(SwitchExpression switchNode, IdentifierNameSyntax? lowerableAssignmentVariable)
{
if (switchNode.Comparison is not null)
{
throw new NotImplementedException("Switch with non-null comparison method");
}
var switchValue = Translate<ExpressionSyntax>(switchNode.SwitchValue);
switch (_context)
{
case ExpressionContext.Statement:
{
var parentLiftedState = _liftedState;
_liftedState = parentLiftedState.CreateChild();
var cases = List(
switchNode.Cases.Select(c => SwitchSection(
labels: List<SwitchLabelSyntax>(
c.TestValues.Select(tv => CaseSwitchLabel(Translate<ExpressionSyntax>(tv)))),
statements: ProcessArmBody(c.Body))));
// LINQ SwitchExpression supports non-literal labels, which C# does not support. This rewrites the switch as a series ofView on GitHub (pinned to 3a2006ef56)