Open sandboxFocusImprove this doc

LA0164: Method Interception Applied to a Method That Returns by Reference

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:

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 true on 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