Skip to content

Handle Invoke being called via a method group - #230

Open
simonmckenzie wants to merge 1 commit into
scottksmith95:masterfrom
simonmckenzie:feature/support-invoke-passed-as-method-group
Open

simonmckenzie wants to merge 1 commit into
scottksmith95:masterfrom
simonmckenzie:feature/support-invoke-passed-as-method-group

Conversation

@simonmckenzie

@simonmckenzie simonmckenzie commented Aug 26, 2026

Copy link
Copy Markdown

This addresses an issue where, if Invoke is passed via a method group, it's wrapped in CreateDelegate and thus isn't inlined. A special handler has been added for this case.

Original issue: #229

Context from issue - I feel this is important because refactoring tools naturally suggest replacing lambdas with method groups, which currently breaks Expand. Refactoring suggestion screenshot is shown below:
Image

Comment on lines +114 to +123
if (
node.NodeType == ExpressionType.Convert
&& node.Operand is MethodCallExpression methodCall &&
methodCall.Method.Name == "CreateDelegate"
&& methodCall.Method.DeclaringType == typeof(MethodInfo)
&& methodCall.Object is ConstantExpression methodInfoConst
&& methodInfoConst.Value is MethodInfo methodInfo
&& methodInfo.Name == nameof(ExtensionsCore.Invoke)
&& methodInfo.DeclaringType == typeof(ExtensionsCore))
{

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just what I've observed and is clearly very specific, and does rely on implementation details.

At the same time, the test passes in all tested scenarios, and does address a real problem 🤷

screenshot of all tests passing

@simonmckenzie
simonmckenzie force-pushed the feature/support-invoke-passed-as-method-group branch from 2b4fe1f to ecb2aa5 Compare August 26, 2026 05:46
Expression<Func<int, bool>> filter = p => p > 1000;
Expression<Func<int[], bool>> anyMeetsFilter = x => x.Any(filter.Invoke);

Assert.Equal("x => x.Any(p => (p > 1000))", anyMeetsFilter.Expand().ToString());

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without the new code, anyMeetsFilter.Expand().ToString() produces this:

x => x.Any(Convert(Boolean Invoke[Int32,Boolean](System.Linq.Expressions.Expression`1[System.Func`2[System.Int32,System.Boolean]], Int32).CreateDelegate(System.Func`2[System.Int32,System.Boolean], p => (p > 1000))))

This addresses an issue where, if `Invoke` is passed via a method group, it's wrapped in `CreateDelegate` and thus isn't inlined. A special handler has been added for this case.
@simonmckenzie
simonmckenzie force-pushed the feature/support-invoke-passed-as-method-group branch from ecb2aa5 to 19ad870 Compare August 27, 2026 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant