| Severity | Error |
| Reported by | PostSharp |
| Message | The aspect "<Aspect>" applied to "<Target>" attempts to introduce a field <Name>of type "<FieldType>" in "<TargetType>", but the field "<Field>" already exists, and the WhenCompatibleFieldExists property of the IntroduceFieldAdviceInstance is Fail. Set it to Ignore to skip the introduction and use this field, or to IntroduceAnother to introduce another field. |
Cause
An aspect attempts to introduce a field in its target type by returning an IntroduceFieldAdviceInstance from ProvideAdvices. Before introducing a new field, PostSharp looks for an existing field that matches the request, in the target type and in the accessible fields of its base types:
- When the request has a Name, the matching field has this name, the requested type, and the same static or instance kind.
- When the request has no name, a matching field has the requested type and kind, whatever its name. LA0271 is then reported when exactly one field matches; when several fields match, PostSharp reports LA0273 instead.
The WhenCompatibleFieldExists property of the request decides what happens with a matching field. Its default value, Fail, reports LA0271, so that the aspect does not silently share a field that the source code or another aspect uses. LA0271 is always an error.
<Name> is the requested name in quotes followed by a space, or nothing when the request has no name. <Target> is the declaration to which the aspect is applied, where the error is located, and <Field> is the field that matches.
In the following example, the [CountCalls] aspect attempts to introduce an int field named callCount in OrderService, which already declares it.
using System;
using System.Collections.Generic;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;
namespace Errors.LA0271_Error;
[PSerializable]
public sealed class CountCallsAttribute : MethodLevelAspect, IAdviceProvider
{
public IEnumerable<AdviceInstance> ProvideAdvices( object targetElement )
{
yield return new IntroduceFieldAdviceInstance( typeof(int) ) { Name = "callCount" };
}
[OnMethodEntryAdvice]
public static void OnEntry( [ImportMember] ref int callCount )
{
callCount++;
}
}
public class OrderService
{
private int callCount;
public int CallCount => this.callCount;
public void ResetCount() => this.callCount = 0;
// The aspect requests a callCount field, which OrderService already declares.
[CountCalls]
public void PlaceOrder( string product )
{
Console.WriteLine( $"Placing an order for {product}." );
}
}
public static class Program
{
public static void Main()
{
var service = new OrderService();
service.PlaceOrder( "a book" );
service.PlaceOrder( "a pen" );
Console.WriteLine( $"{service.CallCount} orders placed." );
}
}
error LA0271: LA0271_Error.cs(34,17): The aspect "Errors.LA0271_Error.CountCallsAttribute" applied to "Errors.LA0271_Error.OrderService.PlaceOrder(System.String)" attempts to introduce a field "callCount" of type "int32" in "Errors.LA0271_Error.OrderService", but the field "Errors.LA0271_Error.OrderService.callCount" already exists, and the WhenCompatibleFieldExists property of the IntroduceFieldAdviceInstance is Fail. Set it to Ignore to skip the introduction and use this field, or to IntroduceAnother to introduce another field.
Resolution
Set the WhenCompatibleFieldExists property of the request to what the aspect must do with the existing field:
- Ignore makes the aspect use the existing field instead of introducing one. This is how the aspect shares a field with the source code or with other aspects.
- IntroduceAnother introduces another field and leaves the existing one alone. With a requested name, the new field gets this name followed by a number.
Otherwise, choose another name, or rename the existing field.
In the following example, the aspect counts the calls in the existing callCount field, which the CallCount property of OrderService exposes.
using System;
using System.Collections.Generic;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;
namespace Errors.LA0271_Fixed;
[PSerializable]
public sealed class CountCallsAttribute : MethodLevelAspect, IAdviceProvider
{
public IEnumerable<AdviceInstance> ProvideAdvices( object targetElement )
{
// Ignore makes the aspect count the calls in the existing callCount field.
yield return new IntroduceFieldAdviceInstance( typeof(int) ) { Name = "callCount", WhenCompatibleFieldExists = IntroduceFieldCompatibleAction.Ignore };
}
[OnMethodEntryAdvice]
public static void OnEntry( [ImportMember] ref int callCount )
{
callCount++;
}
}
public class OrderService
{
private int callCount;
public int CallCount => this.callCount;
public void ResetCount() => this.callCount = 0;
[CountCalls]
public void PlaceOrder( string product )
{
Console.WriteLine( $"Placing an order for {product}." );
}
}
public static class Program
{
public static void Main()
{
var service = new OrderService();
service.PlaceOrder( "a book" );
service.PlaceOrder( "a pen" );
Console.WriteLine( $"{service.CallCount} orders placed." );
}
}
Placing an order for a book.
Placing an order for a pen.
2 orders placed.
See Also
Reference
IntroduceFieldAdviceInstance
IntroduceFieldCompatibleAction
ImportMemberAttribute
Other Resources