Open sandboxFocusImprove this doc

LAMA0267: A template can't convert an extension method group to a delegate

Severity Error
Reported by Metalama.Framework
Message Converting the extension method '<Method>' to a delegate using a method group conversion is not supported in templates. Use a lambda expression that invokes the method instead.

Cause

When a template invokes an extension method on a run-time expression, for instance items.First(), the template compiler rewrites the call as a call to the static method that declares it, for instance Enumerable.First( items ). This rewriting requires an invocation.

C# also lets you convert an extension method to a delegate without invoking it, using a method group conversion, for instance Func<string> f = items.First. The template compiler can't rewrite this syntax, so Metalama reports LAMA0267. In the message, <Method> is the extension method, as bound to its receiver.

In the following example, the template creates a Func<string> delegate from the First extension method.

1using Metalama.Framework.Aspects;
2using System;
3using System.Linq;
4
5namespace Doc.LAMA0267.Error;
6
7public class LogCategoryAttribute : OverrideMethodAspect
8{
9    public override dynamic? OverrideMethod()
10    {
11        var categories = new[] { "Orders", "Billing" };
12
13        // Error: First is an extension method, so it cannot be converted to a delegate with a method group.
14        Func<string> getCategory = categories.First;
15
16        Console.WriteLine( $"[{getCategory()}] Executing {meta.Target.Method.Name}." );
17
18        return meta.Proceed();
19    }
20}
21
1namespace Doc.LAMA0267.Error;
2
3internal class OrderService
4{
5    [LogCategory]
6    public void PlaceOrder( int productId ) { }
7}
8

Resolution

Use a lambda expression that invokes the extension method, for instance () => items.First(). Alternatively, when the delegate type has a parameter for the receiver, convert the static method itself, without a receiver, for instance Enumerable.First<string>.

In the following example, the template uses a lambda expression.

1using Metalama.Framework.Aspects;
2using System;
3using System.Linq;
4
5namespace Doc.LAMA0267.Fixed;
6
7public class LogCategoryAttribute : OverrideMethodAspect
8{
9    public override dynamic? OverrideMethod()
10    {
11        var categories = new[] { "Orders", "Billing" };
12
13        // Fixed: a lambda expression invokes the extension method.
14        Func<string> getCategory = () => categories.First();
15
16        Console.WriteLine( $"[{getCategory()}] Executing {meta.Target.Method.Name}." );
17
18        return meta.Proceed();
19    }
20}
21
Source Code
1namespace Doc.LAMA0267.Fixed;
2



3internal class OrderService
4{
5    [LogCategory]
6    public void PlaceOrder( int productId ) { }
7}
8
Transformed Code
1using System;
2using System.Linq;
3
4namespace Doc.LAMA0267.Fixed;
5
6internal class OrderService
7{
8    [LogCategory]
9    public void PlaceOrder(int productId)
10    {
11        var categories = new[] {
12            "Orders",
13            "Billing"
14        };
15        Func<string> getCategory = () => categories.First();
16        Console.WriteLine($"[{getCategory()}] Executing PlaceOrder.");
17    }
18}
19

See also