Open sandboxFocusImprove this doc

LAMA0250: This use of dynamic isn't allowed in a template

Severity Error
Reported by Metalama.Framework
Message In a template, 'dynamic' cannot be used as the type of a cast, 'as', 'is', or 'default' expression, as the type of a lambda parameter or return value, or as a type argument of a method.

Cause

In a T# template, dynamic stands for a run-time type that's only known when Metalama expands the template. Metalama replaces each dynamic expression with code of the actual type. However, when dynamic is written as a type in the template, Metalama has no actual type to put in its place.

Metalama reports LAMA0250 when a template uses the dynamic type in one of the following places:

  • the target type of a cast, for instance (dynamic) value;
  • the type of an is or as expression;
  • the type of a default expression, default(dynamic);
  • the type of a parameter or the return type of a lambda expression;
  • an explicit type argument of a generic method.

Using dynamic as an array element type, a generic type argument of a type, or a tuple element type is reported as LAMA0227.

In the following example, the aspect returns the default value of the return type when a feature is disabled, and the template uses default(dynamic).

1using Metalama.Framework.Aspects;
2
3namespace Doc.LAMA0250.Error;
4
5public class SkipIfDisabledAttribute : OverrideMethodAspect
6{
7    public override dynamic? OverrideMethod()
8    {
9        if ( !FeatureFlags.IsReportingEnabled )
10        {
11            // Error: default(dynamic) is not allowed in a template.
            Error LAMA0250: In a template, 'dynamic' cannot be used as the type of a cast, 'as', 'is', or 'default' expression, as the type of a lambda parameter or return value, or as a type argument of a method.

12            return default(dynamic);
13        }
14
15        return meta.Proceed();
16    }
17}
18
1namespace Doc.LAMA0250.Error;
2
3public static class FeatureFlags
4{
5    public static bool IsReportingEnabled { get; set; }
6}
7
8internal class ReportService
9{
10    [SkipIfDisabled]
11    public int CountPendingReports() => 42;
12}
13

Resolution

Remove the dynamic type from the expression:

  • To get the default value of the return type of the target method, use meta.Default( meta.Target.Method.ReturnType ), as shown in the following example.
  • Instead of casting an expression to dynamic, use an expression that's already dynamic, such as meta.Proceed() or the Value property of a parameter. To give a type to an expression, use WithType.
  • In lambdas and in type arguments, use the actual type, or build the code with the code model and ExpressionFactory.

1using Metalama.Framework.Aspects;
2
3namespace Doc.LAMA0250.Fixed;
4
5public class SkipIfDisabledAttribute : OverrideMethodAspect
6{
7    public override dynamic? OverrideMethod()
8    {
9        if ( !FeatureFlags.IsReportingEnabled )
10        {
11            // Fixed: meta.Default returns the default value of the return type.
12            return meta.Default( meta.Target.Method.ReturnType );
13        }
14
15        return meta.Proceed();
16    }
17}
18
Source Code
1namespace Doc.LAMA0250.Fixed;
2

3public static class FeatureFlags
4{
5    public static bool IsReportingEnabled { get; set; }
6}
7
8internal class ReportService
9{
10    [SkipIfDisabled]
11    public int CountPendingReports() => 42;
12}
13
Transformed Code
1namespace Doc.LAMA0250.Fixed;
2
3public static class FeatureFlags
4{
5    public static bool IsReportingEnabled { get; set; }
6}
7
8internal class ReportService
9{
10    [SkipIfDisabled]
11    public int CountPendingReports()
12    {
13        if (!FeatureFlags.IsReportingEnabled)
14        {
15            return default;
16        }
17
18        return 42;
19    }
20}
21

See also