Open sandboxFocusImprove this doc

LA0189: Advice Parameter Can Write to an In Argument

Severity Error
Reported by PostSharp
Message Cannot apply the advice "<Advice>" to the method "<TargetMethod>": the advice has a 'ref' or 'out' parameter that binds to the 'in' parameter #<Index> of the target method. Declare the parameter of the advice as 'in'.

Cause

An advice method receives an argument of its target method through a parameter marked with ArgumentAttribute. When the parameter of the advice is ref or out, the advice can write to the argument. An in parameter of the target method is read-only, so PostSharp does not let an advice write to it, and reports LA0189 instead of applying the advice.

<Index> is the zero-based position of the parameter in the target method. The message has no location in the source code: it names the advice and the target method.

In the following example, the OnEntry advice receives the in parameter of Account.Deposit as a ref parameter.

using System;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;

namespace Errors.LA0189_Error;

[PSerializable]
public class LogAmountAttribute : MethodLevelAspect
{
    [OnMethodEntryAdvice]
    // The advice receives the argument as ref, but the target method receives it as in.
    public void OnEntry( [Argument( 0 )] ref decimal amount )
    {
        Console.WriteLine( $"Depositing {amount}" );
    }
}

public class Account
{
    public decimal Balance { get; private set; }

    [LogAmount]
    public void Deposit( in decimal amount )
    {
        this.Balance += amount;
    }
}

public static class Program
{
    public static void Main()
    {
        var account = new Account();
        account.Deposit( 100m );
        Console.WriteLine( $"Balance: {account.Balance}" );
    }
}
error LA0189: LA0189_Error.cs(24,17): Cannot apply the advice "Errors.LA0189_Error.LogAmountAttribute.OnEntry(System.Decimal@)" to the method "Errors.LA0189_Error.Account.Deposit(System.Decimal@)": the advice has a 'ref' or 'out' parameter that binds to the 'in' parameter #0 of the target method. Declare the parameter of the advice as 'in'.

Resolution

Declare the parameter of the advice as in, or pass it by value when the advice does not need the address of the argument. If the advice must change the argument, the target method must declare the parameter as ref.

In the following example, the advice receives the argument as in.

using System;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;

namespace Errors.LA0189_Fixed;

[PSerializable]
public class LogAmountAttribute : MethodLevelAspect
{
    [OnMethodEntryAdvice]
    // The advice receives the argument as in, like the target method.
    public void OnEntry( [Argument( 0 )] in decimal amount )
    {
        Console.WriteLine( $"Depositing {amount}" );
    }
}

public class Account
{
    public decimal Balance { get; private set; }

    [LogAmount]
    public void Deposit( in decimal amount )
    {
        this.Balance += amount;
    }
}

public static class Program
{
    public static void Main()
    {
        var account = new Account();
        account.Deposit( 100m );
        Console.WriteLine( $"Balance: {account.Balance}" );
    }
}
Depositing 100
Balance: 100

See Also

Reference

ArgumentAttribute
OnMethodEntryAdvice

Other Resources

Advice Parameters