Open sandboxFocusImprove this doc

LAMA0555: A union can't hold an instance field, an automatic property or a field-like event

Severity Error
Reported by Metalama.Framework
Message The aspect '<AspectType>' cannot introduce <MemberKind> into the union '<TargetType>' because a union declaration permits no instance field, no automatic property and no field-like event. Introduce a property whose accessors have a body, or an event whose accessors have a body.

Cause

A union declaration, written with the union keyword of C# 15, stores its value in a form that the compiler controls. For this reason, the language forbids members that add state to it: an instance field, an automatic property (which has a hidden field) and a field-like event (which also has a hidden field). Static members, methods, nested types, and properties or events whose accessors have a body are allowed.

When an aspect introduces a union with IntroduceUnion and then calls IntroduceField, IntroduceAutomaticProperty or IntroduceEvent with a field-like event template to add such a member, Metalama reports LAMA0555 instead of letting the C# compiler report an error in generated code that you can't edit. The <MemberKind> placeholder describes the refused member, and <TargetType> is the union.

In the following example, the GenerateResult aspect introduces an automatic property into the union OrderResult.

1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3
4namespace Doc.LAMA0555.Error;
5
6public class GenerateResultAttribute : TypeAspect
7{
8    public override void BuildAspect( IAspectBuilder<INamedType> builder )
9    {
10        var result = builder.IntroduceUnion(
11            "OrderResult",
12            u =>
13            {
14                u.Accessibility = Accessibility.Public;
15                u.AddCase( typeof(int) );
16                u.AddCase( typeof(string) );
17            } );
18
19        // A union cannot hold an automatic property, because it would need a field.
20        builder.With( result.Declaration ).IntroduceAutomaticProperty( "Label", typeof(string) );
21    }
22}
23
1namespace Doc.LAMA0555.Error;
2
3[GenerateResult]
Error LAMA0555: The aspect 'GenerateResult' cannot introduce the automatic property 'Label' into the union 'OrderService.OrderResult' because a union declaration permits no instance field, no automatic property and no field-like event. Introduce a property whose accessors have a body, or an event whose accessors have a body.

4public partial class OrderService { }
5

Resolution

Do one of the following:

  • Introduce a property whose accessors have a body, using IntroduceProperty with a template. Such a property holds no field.
  • Introduce an event with explicit add and remove accessors instead of a field-like event.
  • Introduce a static member, which holds no state of the value.
  • Introduce the member into a regular class or struct instead of the union.

In the following example, the aspect introduces a property with a getter body.

1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3
4namespace Doc.LAMA0555.Fixed;
5
6public class GenerateResultAttribute : TypeAspect
7{
8    public override void BuildAspect( IAspectBuilder<INamedType> builder )
9    {
10        var result = builder.IntroduceUnion(
11            "OrderResult",
12            u =>
13            {
14                u.Accessibility = Accessibility.Public;
15                u.AddCase( typeof(int) );
16                u.AddCase( typeof(string) );
17            } );
18
19        // A property whose accessor has a body holds no field, so a union accepts it.
20        builder.With( result.Declaration ).IntroduceProperty( nameof(Label) );
21    }
22
23    [Template]
24    public string Label
25    {
26        get { return "Order result"; }
27    }
28}
29
Source Code
1namespace Doc.LAMA0555.Fixed;
2
3[GenerateResult]

4public partial class OrderService { }
5
Transformed Code
1namespace Doc.LAMA0555.Fixed;
2
3[GenerateResult]
4public partial class OrderService
5{
6    public union OrderResult(int, string)
7    {
8        public string Label
9        {
10            get
11            {
12                return "Order result";
13            }
14        }
15    }
16}
17

See also