| Severity | Error |
| Reported by | PostSharp |
| Message | Cannot apply the aspect "<Aspect>" to method "<Method>": applying this aspect to a method returning a managed pointer (ref return) is not supported. |
Cause
Method interception replaces the body of the target method with a call to the OnInvoke advice, which receives the return value of the method as an object in ReturnValue. A method declared with ref or ref readonly before its return type returns a reference to a variable, not a value, and this reference cannot be stored as an object. PostSharp therefore reports LA0164 when one of the following is applied to such a method:
- an aspect derived from MethodInterceptionAspect;
- an aspect with an advice method marked with OnMethodInvokeAdvice.
A method that returns by reference usually receives the aspect through multicasting, when the aspect is applied to its class or assembly.
In the following example, the [Log] aspect is multicast to the methods of Inventory, including GetQuantity, which returns a reference to an element of an array. PostSharp reports the error on the class that carries the multicast attribute, and names the method in the message.
using System;
using PostSharp.Aspects;
using PostSharp.Extensibility;
using PostSharp.Serialization;
namespace Errors.LA0164_Error;
[PSerializable]
public class LogAttribute : MethodInterceptionAspect
{
public override void OnInvoke( MethodInterceptionArgs args )
{
Console.WriteLine( $"Calling {args.Method.Name}." );
args.Proceed();
}
}
// The aspect is multicast to the methods of the class, including GetQuantity, which returns a reference.
[Log( AttributeTargetElements = MulticastTargets.Method )]
public class Inventory
{
private readonly int[] _quantities = new int[10];
public void Restock( int slot, int quantity ) => this.GetQuantity( slot ) += quantity;
public ref int GetQuantity( int slot ) => ref this._quantities[slot];
}
public static class Program
{
public static void Main()
{
Inventory inventory = new();
inventory.Restock( 3, 5 );
Console.WriteLine( $"Slot 3 holds {inventory.GetQuantity( 3 )} items." );
}
}
error LA0164: LA0164_Error.cs(20,14): Cannot apply the aspect "Errors.LA0164_Error.LogAttribute" to method "Errors.LA0164_Error.Inventory.GetQuantity(System.Int32)": applying this aspect to a method returning a managed pointer (ref return) is not supported.
Resolution
- Exclude the method from the multicast, with a custom attribute of the aspect that sets AttributeExclude to
trueon the method. - Restrict the multicast with a filter such as AttributeTargetMembers, so that it does not match the method.
- If the method does not need to return a reference, make it return the value.
In the following example, GetQuantity is excluded from the multicast, and the aspect still intercepts Restock.
using System;
using PostSharp.Aspects;
using PostSharp.Extensibility;
using PostSharp.Serialization;
namespace Errors.LA0164_Fixed;
[PSerializable]
public class LogAttribute : MethodInterceptionAspect
{
public override void OnInvoke( MethodInterceptionArgs args )
{
Console.WriteLine( $"Calling {args.Method.Name}." );
args.Proceed();
}
}
// The aspect is multicast to the methods of the class.
[Log( AttributeTargetElements = MulticastTargets.Method )]
public class Inventory
{
private readonly int[] _quantities = new int[10];
public void Restock( int slot, int quantity ) => this.GetQuantity( slot ) += quantity;
// The method that returns a reference is excluded from the multicast.
[Log( AttributeExclude = true )]
public ref int GetQuantity( int slot ) => ref this._quantities[slot];
}
public static class Program
{
public static void Main()
{
Inventory inventory = new();
inventory.Restock( 3, 5 );
Console.WriteLine( $"Slot 3 holds {inventory.GetQuantity( 3 )} items." );
}
}
Calling Restock.
Slot 3 holds 5 items.
See Also
Reference
MethodInterceptionAspect
OnMethodInvokeAdvice
AttributeExclude
Other Resources
Intercepting Methods
Adding Aspects to Multiple Declarations Using Attributes