Open sandboxFocusImprove this doc

LA0225: Argument Index Out of Range

Severity Error
Reported by PostSharp
Message The parameter "<Parameter>" of the advice "<Advice>" is bound by [Argument(<Index>)], but "<TargetMethod>" has no parameter at this index.

Cause

The ArgumentAttribute(int) constructor binds a parameter of an advice to the argument at a zero-based index in the parameter list of the target method. PostSharp checks the index for each target method of the advice. When the index is not lower than the number of parameters of a target method, it reports LA0225 on that method. A negative index reports LA0216 instead, whatever the target.

The same aspect often applies to methods whose parameters differ, for example through multicasting. An index that is valid for one target can then be out of range for another one. When the advice uses a pointcut that skips the targets whose signature does not match, such as MatchPointcut, PostSharp skips the target instead of reporting the error.

In the following example, the [LogAmount] aspect reads the amount as the second argument, which is right for Transfer but not for Deposit.

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

namespace Errors.LA0225_Error;

[PSerializable]
public sealed class LogAmountAttribute : MethodLevelAspect
{
    [OnMethodEntryAdvice]
    public void OnEntry( [DeclarationName] string methodName, [Argument( 1 )] decimal amount )
    {
        Console.WriteLine( $"{methodName}: {amount}" );
    }
}

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

    [LogAmount]
    public void Transfer( string recipient, decimal amount )
    {
        this.Balance -= amount;
    }

    // The amount is the first and only parameter of this method, not the second one.
    [LogAmount]
    public void Deposit( decimal amount )
    {
        this.Balance += amount;
    }
}

public static class Program
{
    public static void Main()
    {
        Account account = new();
        account.Deposit( 100 );
        account.Transfer( "Bob", 30 );
    }
}
error LA0225: LA0225_Error.cs(30,17): The parameter "amount" of the advice "Errors.LA0225_Error.LogAmountAttribute.OnEntry(System.String, System.Decimal)" is bound by [Argument(1)], but "Errors.LA0225_Error.Account.Deposit(System.Decimal)" has no parameter at this index.

Resolution

  • Select the argument by its name with ArgumentAttribute(string), or by its type with the constructor without parameters, so that its position does not matter.
  • Otherwise, apply the aspect only to methods that have a parameter at this index.

In the following example, the [LogAmount] aspect selects the amount argument by its name.

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

namespace Errors.LA0225_Fixed;

[PSerializable]
public sealed class LogAmountAttribute : MethodLevelAspect
{
    // The argument is selected by its name, whatever its position.
    [OnMethodEntryAdvice]
    public void OnEntry( [DeclarationName] string methodName, [Argument( "amount" )] decimal amount )
    {
        Console.WriteLine( $"{methodName}: {amount}" );
    }
}

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

    [LogAmount]
    public void Transfer( string recipient, decimal amount )
    {
        this.Balance -= amount;
    }

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

public static class Program
{
    public static void Main()
    {
        Account account = new();
        account.Deposit( 100 );
        account.Transfer( "Bob", 30 );
    }
}
Deposit: 100
Transfer: 30

See Also

Reference

ArgumentAttribute
MatchPointcut

Other Resources

Advice Parameters