| 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
addandremoveaccessors 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
1namespace Doc.LAMA0555.Fixed;
2
3[GenerateResult]
4public partial class OrderService { }
5
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