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

  1. Avoid SwitchExpression overloads that set a custom Comparison when the tree will be translated to C#.
  2. Rewrite the switch to use default equality matching so Comparison stays null.
  3. 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

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


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 of

View on GitHub (pinned to 3a2006ef56)