{"record":{"id":"10da0d465e62df00","repo":"dotnet/efcore","slug":"switch-with-non-null-comparison-method","errorCode":null,"errorMessage":"Switch with non-null comparison method","messagePattern":"Switch with non-null comparison method","errorType":"exception","errorClass":"NotImplementedException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs","lineNumber":2199,"sourceCode":"    /// <inheritdoc />\n    protected override Expression VisitSwitch(SwitchExpression switchNode)\n    {\n        Result = TranslateSwitch(switchNode, lowerableAssignmentVariable: null);\n\n        return switchNode;\n    }\n\n    /// <summary>\n    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to\n    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in\n    ///     any release. You should only use it directly in your code with extreme caution and knowing that\n    ///     doing so can result in application failures when updating to a new Entity Framework Core release.\n    /// </summary>\n    protected virtual CSharpSyntaxNode TranslateSwitch(SwitchExpression switchNode, IdentifierNameSyntax? lowerableAssignmentVariable)\n    {\n        if (switchNode.Comparison is not null)\n        {\n            throw new NotImplementedException(\"Switch with non-null comparison method\");\n        }\n\n        var switchValue = Translate<ExpressionSyntax>(switchNode.SwitchValue);\n\n        switch (_context)\n        {\n            case ExpressionContext.Statement:\n            {\n                var parentLiftedState = _liftedState;\n                _liftedState = parentLiftedState.CreateChild();\n\n                var cases = List(\n                    switchNode.Cases.Select(c => SwitchSection(\n                        labels: List<SwitchLabelSyntax>(\n                            c.TestValues.Select(tv => CaseSwitchLabel(Translate<ExpressionSyntax>(tv)))),\n                        statements: ProcessArmBody(c.Body))));\n\n                // LINQ SwitchExpression supports non-literal labels, which C# does not support. This rewrites the switch as a series of","sourceCodeStart":2181,"sourceCodeEnd":2217,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs#L2181-L2217","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nExpression.Switch(value, comparer: myComparer, cases...);\n// after\nExpression.Switch(value, cases...); // omit the comparison argument","handlingStrategy":"validation","validationCode":"// Reject switch expressions carrying a comparison before translating\nstatic bool HasCustomComparison(Expression e)\n{\n    bool found = false;\n    new SwitchChecker { Found = () => found = true }.Visit(e);\n    return found;\n}\nclass SwitchChecker : ExpressionVisitor\n{\n    public Action Found;\n    protected override Expression VisitSwitch(SwitchExpression node)\n    {\n        if (node.Comparison is not null) Found();\n        return base.VisitSwitch(node);\n    }\n}","typeGuard":"static bool IsTranslatableSwitch(SwitchExpression s) => s.Comparison is null;","tryCatchPattern":"try { var csharp = translator.Translate(expr); }\ncatch (NotImplementedException ex) when (ex.Message.Contains(\"Switch with non-null comparison\"))\n{ throw new InvalidOperationException(\"Custom-comparison switch expressions cannot be translated to C#.\", ex); }","preventionTips":["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."],"tags":["expression-trees","precompiled-queries","compiled-model","linq","switch"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}