| 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
1namespace Doc.LAMA0267.Fixed;
2
3internal class OrderService
4{
5 [LogCategory]
6 public void PlaceOrder( int productId ) { }
7}
8
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