Open sandboxFocusImprove this doc

LAMA0502: The introduced member can't override the base member

Severity Error
Reported by Metalama.Framework
Message The aspect '<AspectType>' cannot introduce member '<Member>' into type '<TargetType>' because it is already defined in type '<DeclaringType>' and is static, non-virtual or sealed, so it cannot be overridden. Use OverrideStrategy.New to hide the existing member, or OverrideStrategy.Ignore to keep it.

Cause

When an aspect introduces a method, property, event or indexer with the OverrideStrategy.Override strategy, and a member with the same signature already exists in a base type, Metalama introduces an override member in the target type. As in C#, this is only possible when the base member is virtual, abstract or override, and isn't sealed.

Metalama reports LAMA0502 when the base member can't be overridden because it's static, non-virtual or sealed. In the message, <TargetType> is the target type and <DeclaringType> is the base type that defines the existing member.

In the following example, the Resettable aspect overrides the Reset method in ShoppingCart, but the Reset method of the base class Cart isn't virtual.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0502.Error;
5
6public class ResettableAttribute : TypeAspect
7{
8    [Introduce( WhenExists = OverrideStrategy.Override )]
9    public void Reset()
10    {
11        Console.WriteLine( "Resetting the object." );
12        meta.Proceed();
13    }
14}
15
1using System.Collections.Generic;
2
3namespace Doc.LAMA0502.Error;
4
5internal class Cart
6{
7    protected readonly List<string> Items = new();
8
9    // Error: the method is not virtual, so the aspect cannot override it in ShoppingCart.
10    public void Reset() => this.Items.Clear();
11}
12
13[Resettable]
Error LAMA0502: The aspect 'Resettable' cannot introduce member 'ShoppingCart.Reset()' into type 'ShoppingCart' because it is already defined in type 'Cart' and is static, non-virtual or sealed, so it cannot be overridden. Use OverrideStrategy.New to hide the existing member, or OverrideStrategy.Ignore to keep it.

14internal partial class ShoppingCart : Cart
15{
16    public void Add( string item ) => this.Items.Add( item );
17}
18

Resolution

Depending on your intent, do one of the following:

  • If you own the base type, make the base member virtual, or remove its sealed modifier.
  • Use OverrideStrategy.New to introduce a member that hides the base member with the new modifier. Code that calls the member through the base type still calls the base member.
  • Use OverrideStrategy.Ignore to keep the base member and skip the introduction.

In the following example, the Reset method of Cart is made virtual, so the aspect introduces an override method in ShoppingCart.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0502.Fixed;
5
6public class ResettableAttribute : TypeAspect
7{
8    [Introduce( WhenExists = OverrideStrategy.Override )]
9    public void Reset()
10    {
11        Console.WriteLine( "Resetting the object." );
12        meta.Proceed();
13    }
14}
15
Source Code
1using System.Collections.Generic;
2

3namespace Doc.LAMA0502.Fixed;
4
5internal class Cart
6{
7    protected readonly List<string> Items = new();
8
9    // Fixed: the method is virtual, so the aspect can override it in ShoppingCart.
10    public virtual void Reset() => this.Items.Clear();
11}
12
13[Resettable]
14internal partial class ShoppingCart : Cart
15{
16    public void Add( string item ) => this.Items.Add( item );
17}
18
Transformed Code
1using System;
2using System.Collections.Generic;
3
4namespace Doc.LAMA0502.Fixed;
5
6internal class Cart
7{
8    protected readonly List<string> Items = new();
9
10    // Fixed: the method is virtual, so the aspect can override it in ShoppingCart.
11    public virtual void Reset() => this.Items.Clear();
12}
13
14[Resettable]
15internal partial class ShoppingCart : Cart
16{
17    public void Add(string item) => this.Items.Add(item);
18
19    public override void Reset()
20    {
21        Console.WriteLine("Resetting the object.");
22        base.Reset();
23    }
24}
25

See also