| Severity | Error |
| Reported by | PostSharp |
| Message | The aspect "<Aspect>" applied to "<Target>" attempts to introduce a field of type "<FieldType>" in "<TargetType>" without a name, and several existing fields of this type could be used instead: <Fields>. Give the IntroduceFieldAdviceInstance a name, or set its WhenCompatibleFieldExists property to IntroduceAnother to introduce a new field. |
Cause
An aspect attempts to introduce a field in its target type by returning an IntroduceFieldAdviceInstance. When the request has no Name, PostSharp recognizes an existing field by its type and its static or instance kind only, among the fields of the target type and the accessible fields of its base types. When several fields match, PostSharp cannot choose one and reports LA0273.
This happens whatever the WhenCompatibleFieldExists property of the request, except IntroduceAnother, which introduces a new field without choosing among the existing ones. When exactly one field matches and WhenCompatibleFieldExists is Fail, PostSharp reports LA0271 instead. LA0273 is always an error.
<Target> is the declaration to which the aspect is applied, where the error is located, and <Fields> lists the matching fields.
In the following example, the [CountCalls] aspect attempts to introduce an int field without a name, and OrderService declares two int fields, callCount and failureCount.
using System;
using System.Collections.Generic;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;
namespace Errors.LA0273_Error;
[PSerializable]
public sealed class CountCallsAttribute : MethodLevelAspect, IAdviceProvider
{
public IEnumerable<AdviceInstance> ProvideAdvices( object targetElement )
{
yield return new IntroduceFieldAdviceInstance( typeof(int) ) { WhenCompatibleFieldExists = IntroduceFieldCompatibleAction.Ignore };
}
[OnMethodEntryAdvice]
public static void OnEntry( [ImportMember( "callCount" )] ref int callCount )
{
callCount++;
}
}
public class OrderService
{
private int callCount;
private int failureCount;
public int CallCount => this.callCount;
public int FailureCount => this.failureCount;
public void ResetCounts()
{
this.callCount = 0;
this.failureCount = 0;
}
// The aspect requests an int field without a name, and OrderService declares two.
[CountCalls]
public void PlaceOrder( string product )
{
if ( product.Length == 0 )
{
this.failureCount++;
return;
}
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( "" );
Console.WriteLine( $"{service.CallCount} calls, {service.FailureCount} failure." );
}
}
error LA0273: LA0273_Error.cs(41,17): The aspect "Errors.LA0273_Error.CountCallsAttribute" applied to "Errors.LA0273_Error.OrderService.PlaceOrder(System.String)" attempts to introduce a field of type "int32" in "Errors.LA0273_Error.OrderService" without a name, and several existing fields of this type could be used instead: "callCount", "failureCount". Give the IntroduceFieldAdviceInstance a name, or set its WhenCompatibleFieldExists property to IntroduceAnother to introduce a new field.
Resolution
- To use one of the existing fields, set the Name of the request to the name of this field, with WhenCompatibleFieldExists set to Ignore.
- To give the aspect a field of its own, set WhenCompatibleFieldExists to IntroduceAnother. The new field gets a generated name. An advice that imports this field by its type with ImportMemberAttribute receives it, because the fields that the aspect requested win over the other fields of the type.
In the following example, the request names the callCount field, and the aspect counts the calls in this field.
using System;
using System.Collections.Generic;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;
namespace Errors.LA0273_Fixed;
[PSerializable]
public sealed class CountCallsAttribute : MethodLevelAspect, IAdviceProvider
{
public IEnumerable<AdviceInstance> ProvideAdvices( object targetElement )
{
// The name selects the callCount field.
yield return new IntroduceFieldAdviceInstance( typeof(int) ) { Name = "callCount", WhenCompatibleFieldExists = IntroduceFieldCompatibleAction.Ignore };
}
[OnMethodEntryAdvice]
public static void OnEntry( [ImportMember( "callCount" )] ref int callCount )
{
callCount++;
}
}
public class OrderService
{
private int callCount;
private int failureCount;
public int CallCount => this.callCount;
public int FailureCount => this.failureCount;
public void ResetCounts()
{
this.callCount = 0;
this.failureCount = 0;
}
[CountCalls]
public void PlaceOrder( string product )
{
if ( product.Length == 0 )
{
this.failureCount++;
return;
}
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( "" );
Console.WriteLine( $"{service.CallCount} calls, {service.FailureCount} failure." );
}
}
Placing an order for a book.
2 calls, 1 failure.
See Also
Reference
IntroduceFieldAdviceInstance
IntroduceFieldCompatibleAction
ImportMemberAttribute
Other Resources