| Severity | Error |
| Reported by | Metalama.Framework |
| Message | Expression-bodied lambdas whose expression is of type 'dynamic' are not supported. Cast the expression to a non-dynamic type, for example 'object' or 'IExpression'. Alternatively, use a local function, or, for a void expression, a lambda with a block body. |
Cause
In a template, many expressions have the type dynamic, for instance the Value property of a parameter, meta.This, or the result of meta.Proceed(). When such an expression is the body of a lambda, the lambda returns dynamic, which can change the type of the surrounding expression, for instance the result of a LINQ Select call. Metalama doesn't support this case.
Metalama reports LAMA0263 for any lambda in a template whose expression body has the type dynamic. Lambdas with a block body aren't concerned.
In the following example, a lambda returns the value of the first parameter of the target method, which is dynamic.
1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0263.Error;
5
6public class LogFirstArgumentAttribute : OverrideMethodAspect
7{
8 public override dynamic? OverrideMethod()
9 {
10 // Error: the body of the lambda is a dynamic expression.
Error LAMA0263: Expression-bodied lambdas whose expression is of type 'dynamic' are not supported. Cast the expression to a non-dynamic type, for example 'object' or 'IExpression'. Alternatively, use a local function, or, for a void expression, a lambda with a block body.
11 Func<object?> getArgument = () => meta.Target.Parameters[0].Value;
12 Console.WriteLine( $"First argument: {getArgument()}" );
13
14 return meta.Proceed();
15 }
16}
17
1namespace Doc.LAMA0263.Error;
2
3internal class Calculator
4{
5 [LogFirstArgument]
6 public int Square( int value ) => value * value;
7}
8
Resolution
Do one of the following:
- Cast the body of the lambda to a non-dynamic type. In a run-time lambda, cast it to the type you need, for instance
object, as in the following example. In a compile-time lambda, for instance in aSelectcall onmeta.Target.Parameters, cast it to IExpression. - Use a local function instead of the lambda.
- If the expression is
void, use a lambda with a block body.
1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0263.Fixed;
5
6public class LogFirstArgumentAttribute : OverrideMethodAspect
7{
8 public override dynamic? OverrideMethod()
9 {
10 // Fixed: the cast to object gives the body of the lambda a non-dynamic type.
11 Func<object?> getArgument = () => (object?) meta.Target.Parameters[0].Value;
12 Console.WriteLine( $"First argument: {getArgument()}" );
13
14 return meta.Proceed();
15 }
16}
17
Source Code
1namespace Doc.LAMA0263.Fixed;
2
3internal class Calculator
4{
5 [LogFirstArgument]
6 public int Square( int value ) => value * value;
7}
8
Transformed Code
1using System;
2
3namespace Doc.LAMA0263.Fixed;
4
5internal class Calculator
6{
7 [LogFirstArgument]
8 public int Square(int value)
9 {
10 Func<object?> getArgument = () => (object?)value;
11 Console.WriteLine($"First argument: {getArgument()}");
12 return value * value;
13 }
14}
15