| Severity | Error |
| Reported by | Metalama.Framework |
| Message | The aspect '<Aspect>' cannot introduce indexer '<Indexer>' into '<ExtensionBlock>' because the indexer has an 'init' accessor, which the language forbids for an extension member. |
Cause
An extension block adds members to an existing type without changing that type. The C# language doesn't allow an init accessor in a member of an extension block, because such an accessor is meant to run while an object is being initialized, and an extension block doesn't take part in the construction of the extended type.
Metalama reports LAMA0542 when an aspect calls IntroduceIndexer on an extension block and makes the indexer init-only, for instance by setting its Writeability to InitOnly.
In the following example, the aspect introduces an init-only indexer into the extension block of the IntExtensions class.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System;
4using System.Linq;
5
6namespace Doc.LAMA0542.Error;
7
8public class ItemIndexerAttribute : TypeAspect
9{
10 public override void BuildAspect( IAspectBuilder<INamedType> builder )
11 {
12 var extensionBlock = builder.With( builder.Target.ExtensionBlocks.Single() );
13
14 extensionBlock.IntroduceIndexer(
15 typeof(int),
16 nameof(this.GetItem),
17 nameof(this.SetItem),
18 // An extension member cannot have an init accessor.
19 buildIndexer: indexer => indexer.Writeability = Writeability.InitOnly );
20 }
21
22 [Template]
23 public string GetItem( int index )
24 {
25 Console.WriteLine( "Get." );
26
27 return index.ToString();
28 }
29
30 [Template]
31 public void SetItem( int index, string value )
32 {
33 Console.WriteLine( "Set." );
34 }
35}
36
1namespace Doc.LAMA0542.Error;
2
3// Error: the aspect introduces an indexer with an init accessor into the extension block.
4[ItemIndexer]
Error LAMA0542: The aspect 'ItemIndexer' cannot introduce indexer 'IntExtensions.extension(int).this[int]' into 'IntExtensions.extension(int)' because the indexer has an 'init' accessor, which the language forbids for an extension member.
5internal static class IntExtensions
6{
7 extension( int number )
8 {
9 }
10}
11
Resolution
Introduce the indexer with a regular set accessor, or without a set accessor if the indexer is read-only. In the following example, the aspect no longer makes the indexer init-only.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System;
4using System.Linq;
5
6namespace Doc.LAMA0542.Fixed;
7
8public class ItemIndexerAttribute : TypeAspect
9{
10 public override void BuildAspect( IAspectBuilder<INamedType> builder )
11 {
12 var extensionBlock = builder.With( builder.Target.ExtensionBlocks.Single() );
13
14 // The indexer has a regular set accessor.
15 extensionBlock.IntroduceIndexer( typeof(int), nameof(this.GetItem), nameof(this.SetItem) );
16 }
17
18 [Template]
19 public string GetItem( int index )
20 {
21 Console.WriteLine( "Get." );
22
23 return index.ToString();
24 }
25
26 [Template]
27 public void SetItem( int index, string value )
28 {
29 Console.WriteLine( "Set." );
30 }
31}
32
1namespace Doc.LAMA0542.Fixed;
2
3// The indexer is introduced with a regular set accessor.
4[ItemIndexer]
5internal static class IntExtensions
6{
7 extension( int number )
8 {
9 }
10}
11
1using System;
2
3namespace Doc.LAMA0542.Fixed;
4
5// The indexer is introduced with a regular set accessor.
6[ItemIndexer]
7internal static class IntExtensions
8{
9 extension(int number)
10 {
11 public string this[int index]
12 {
13 get
14 {
15 Console.WriteLine("Get.");
16 return index.ToString();
17 }
18 set
19 {
20 Console.WriteLine("Set.");
21 }
22 }
23 }
24}
25