Open sandboxFocusImprove this doc

LAMA0284: The scope of a lambda or anonymous method can't be determined

Severity Error
Reported by Metalama.Framework
Message The scope of the anonymous method or lambda expression with a block body cannot be determined. Use 'meta.RunTime' or 'meta.CompileTime' to resolve the ambiguity.

Cause

In a template, every statement is either compile-time, meaning that it runs during compilation, or run-time, meaning that it's copied to the generated code. For a lambda expression with an expression body, Metalama infers the scope from the expression. For a lambda expression with a block body, or for an anonymous method (delegate { ... }), Metalama must learn the scope from the context, for instance from the run-time method to which the lambda is passed as an argument.

Metalama reports LAMA0284 when such a lambda or anonymous method appears in a context that doesn't determine its scope, for instance when it's assigned to a local variable.

In the following example, a lambda with a block body is assigned to a local variable of type Action.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0284.Error;
5
6public class LogReturnValueAttribute : OverrideMethodAspect
7{
8    public override dynamic? OverrideMethod()
9    {
10        // Metalama can't determine whether this lambda block is compile-time or run-time.
        Error LAMA0284: The scope of the anonymous method or lambda expression with a block body cannot be determined. Use 'meta.RunTime' or 'meta.CompileTime' to resolve the ambiguity.

11        Action<object?> log = value => { Console.WriteLine( value?.ToString() ); };
12
13        var result = meta.Proceed();
14        log( result );
15
16        return result;
17    }
18}
19
1namespace Doc.LAMA0284.Error;
2
3public class Calculator
4{
5    [LogReturnValue]
6    public int Add( int a, int b ) => a + b;
7}
8

Resolution

Make the scope of the lambda or anonymous method explicit:

  • To include it in the generated code, wrap it in meta.RunTime, for instance meta.RunTime( new Action<object?>( ... ) ), as in the following example.
  • To run it at compile time, wrap it in meta.CompileTime.

Alternatively, pass the lambda directly as an argument of a run-time method, which determines its scope.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0284.Fixed;
5
6public class LogReturnValueAttribute : OverrideMethodAspect
7{
8    public override dynamic? OverrideMethod()
9    {
10        // meta.RunTime makes the lambda block run-time.
11        var log = meta.RunTime( new Action<object?>( value => { Console.WriteLine( value?.ToString() ); } ) );
12
13        var result = meta.Proceed();
14        log( result );
15
16        return result;
17    }
18}
19
Source Code
1namespace Doc.LAMA0284.Fixed;
2


3public class Calculator
4{
5    [LogReturnValue]
6    public int Add( int a, int b ) => a + b;
7}
8
Transformed Code
1using System;
2
3namespace Doc.LAMA0284.Fixed;
4
5public class Calculator
6{
7    [LogReturnValue]
8    public int Add(int a, int b)
9    {
10        var log = new Action<object?>(value => Console.WriteLine(value?.ToString()));
11        int result;
12        result = a + b;
13        log(result);
14        return result;
15    }
16}
17

See also