| Severity | Error |
| Reported by | Metalama.Framework |
| Message | The template call '<Call>' cannot be part of another expression or statement. A template can only be called as a stand-alone statement. |
Cause
A template can call an auxiliary template, a method marked with [Template]. Metalama doesn't generate a method call: it expands the auxiliary template and inserts the statements it generates at the place of the call. For this reason, the call must be a stand-alone statement, like this.Log();.
Metalama reports LAMA0270 when the call to an auxiliary template is part of another expression or statement, for instance:
- the expression of a
returnstatement or the initializer of a local variable; - an argument of another method call;
- a part of a
forstatement, such as its condition; - a conditional access, like
templates?.Log(); - the initializer of a field introduced with [Introduce].
Even when the auxiliary template returns a value, you can't use this value in an expression: its return statements become return statements of the target method.
In the following example, the OverrideMethod template returns the result of the Log auxiliary template.
1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0270.Error;
5
6public class LogAttribute : OverrideMethodAspect
7{
8 public override dynamic? OverrideMethod()
9 {
10 // Error: the call to the Log template is part of a return statement.
Error LAMA0270: The template call 'this.Log()' cannot be part of another expression or statement. A template can only be called as a stand-alone statement.
11 return this.Log();
12 }
13
14 [Template]
15 private dynamic? Log()
16 {
17 Console.WriteLine( $"Executing {meta.Target.Method}." );
18
19 return meta.Proceed();
20 }
21}
22
1namespace Doc.LAMA0270.Error;
2
3internal class Calculator
4{
5 [Log]
6 public int Add( int a, int b ) => a + b;
7}
8
Resolution
Call the auxiliary template as a stand-alone statement. If you need a value, produce it outside of the auxiliary template:
- Make the auxiliary template
void, call it as a statement, and keep the code that produces the value, like meta.Proceed(), in the calling template, as in the following example. - If the auxiliary template must end the target method with a value, make it
voidand call meta.Return(...) in it to generate thereturnstatement. - If you only need to compute a compile-time value, use a compile-time method instead of a template.
1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0270.Fixed;
5
6public class LogAttribute : OverrideMethodAspect
7{
8 public override dynamic? OverrideMethod()
9 {
10 // Fixed: the Log template is called as a stand-alone statement.
11 this.Log();
12
13 return meta.Proceed();
14 }
15
16 [Template]
17 private void Log()
18 {
19 Console.WriteLine( $"Executing {meta.Target.Method}." );
20 }
21}
22
1namespace Doc.LAMA0270.Fixed;
2
3internal class Calculator
4{
5 [Log]
6 public int Add( int a, int b ) => a + b;
7}
8
1using System;
2
3namespace Doc.LAMA0270.Fixed;
4
5internal class Calculator
6{
7 [Log]
8 public int Add(int a, int b)
9 {
10 Console.WriteLine("Executing Calculator.Add(int, int).");
11 return a + b;
12 }
13}
14