Open sandboxFocusImprove this doc

LAMA0225: A dynamic local variable can't be initialized with null or default

Severity Error
Reported by Metalama.Framework
Message The 'dynamic' keyword cannot be used in the local variable '<Variable>' because it is initialized with a target-typed expression (such as 'default' or 'null'). Initialize the variable with an expression of type 'dynamic', for example 'meta.Default( type )'.

Cause

In a T# template, dynamic stands for a run-time type that's only known when Metalama expands the template. Metalama infers the actual type of a dynamic local variable from its initializer. A target-typed expression has no type of its own: it takes the type of its destination, so it can't give a type to the variable.

Metalama reports LAMA0225 when a template initializes a local variable of type dynamic (or dynamic?) with a target-typed expression: the null or default literal, a throw expression, or a stackalloc expression, possibly in parentheses. The placeholder of the message is the name of the variable.

In the following example, the aspect returns the default value of the return type when the method throws an exception, and the template initializes result with null.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0225.Error;
5
6public class ReturnDefaultOnExceptionAttribute : OverrideMethodAspect
7{
8    public override dynamic? OverrideMethod()
9    {
10        // Error: null is target-typed, so it can't initialize a variable of type dynamic.
        Error LAMA0225: The 'dynamic' keyword cannot be used in the local variable 'result' because it is initialized with a target-typed expression (such as 'default' or 'null'). Initialize the variable with an expression of type 'dynamic', for example 'meta.Default( type )'.

11        dynamic? result = null;
12
13        try
14        {
15            result = meta.Proceed();
16        }
17        catch ( Exception e )
18        {
19            Console.WriteLine( $"{meta.Target.Method.Name} failed: {e.Message}" );
20        }
21
22        return result;
23    }
24}
25
1namespace Doc.LAMA0225.Error;
2
3internal class Calculator
4{
5    [ReturnDefaultOnException]
6    public int Divide( int a, int b ) => a / b;
7}
8

Resolution

Initialize the variable with an expression of type dynamic. 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.

Casting the initializer doesn't help: a cast to dynamic isn't allowed in templates, and a cast to another type doesn't produce a dynamic expression. If you know the type of the variable, declare it with this type instead of dynamic.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0225.Fixed;
5
6public class ReturnDefaultOnExceptionAttribute : OverrideMethodAspect
7{
8    public override dynamic? OverrideMethod()
9    {
10        // Fixed: meta.Default returns the default value of the return type as a dynamic expression.
11        dynamic? result = meta.Default( meta.Target.Method.ReturnType );
12
13        try
14        {
15            result = meta.Proceed();
16        }
17        catch ( Exception e )
18        {
19            Console.WriteLine( $"{meta.Target.Method.Name} failed: {e.Message}" );
20        }
21
22        return result;
23    }
24}
25
Source Code
1namespace Doc.LAMA0225.Fixed;
2


3internal class Calculator
4{
5    [ReturnDefaultOnException]
6    public int Divide( int a, int b ) => a / b;
7}
8
Transformed Code
1using System;
2
3namespace Doc.LAMA0225.Fixed;
4
5internal class Calculator
6{
7    [ReturnDefaultOnException]
8    public int Divide(int a, int b)
9    {
10        var result = default(int);
11        try
12        {
13            result = a / b;
14        }
15        catch (Exception e)
16        {
17            Console.WriteLine($"Divide failed: {e.Message}");
18        }
19
20        return result;
21    }
22}
23

See also