Open sandboxFocusImprove this doc

LA0227: No Argument of the Bound Type

Severity Error
Reported by PostSharp
Message The parameter "<Parameter>" of the advice "<Advice>" is bound by [Argument] to an argument of its type, but "<TargetMethod>" has no parameter whose type can be assigned to "<ParameterType>" without conversion, except boxing, or has exactly this type when the advice parameter is passed by reference.

Cause

The constructor of ArgumentAttribute without parameters binds a parameter of an advice to the argument of the target method whose type matches the type of the advice parameter. An argument matches when:

  • the advice parameter is passed by value, and the type of the argument can be assigned to <ParameterType> without conversion, except boxing. For instance, an object parameter matches an argument of any type, but a long parameter does not match an int argument;
  • the advice parameter is passed by reference, with in, ref or out, and the argument has exactly its type;
  • the advice parameter is of a type parameter of the advice, which matches any argument.

When no argument of a target method matches, PostSharp reports LA0227 on that method. When several arguments match, PostSharp reports LA0228, unless the AmbiguityResolution property selects one of them. 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 [CheckCancellation] aspect receives the CancellationToken argument of the target method, but BuildReport has none.

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

namespace Errors.LA0227_Error;

[PSerializable]
public sealed class CheckCancellationAttribute : MethodLevelAspect
{
    [OnMethodEntryAdvice]
    public void OnEntry( [Argument] CancellationToken cancellationToken )
    {
        cancellationToken.ThrowIfCancellationRequested();
    }
}

public class ReportService
{
    // The method has no parameter of type CancellationToken.
    [CheckCancellation]
    public string BuildReport( string title ) => $"Report: {title}";
}

public static class Program
{
    public static void Main()
    {
        Console.WriteLine( new ReportService().BuildReport( "Sales" ) );
    }
}
error LA0227: LA0227_Error.cs(23,19): The parameter "cancellationToken" of the advice "Errors.LA0227_Error.CheckCancellationAttribute.OnEntry(System.Threading.CancellationToken)" is bound by [Argument] to an argument of its type, but "Errors.LA0227_Error.ReportService.BuildReport(System.String)" has no parameter whose type can be assigned to "System.Threading.CancellationToken" without conversion, except boxing, or has exactly this type when the advice parameter is passed by reference.

Resolution

  • Add a parameter of the expected type to the target method.
  • Change the type of the advice parameter to a type that the argument can be assigned to, or pass the parameter by value to accept boxing.
  • Otherwise, apply the aspect only to methods that have an argument of this type, or use MatchPointcut in a type-level aspect to skip the other methods.

In the following example, BuildReport receives the CancellationToken that the aspect checks.

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

namespace Errors.LA0227_Fixed;

[PSerializable]
public sealed class CheckCancellationAttribute : MethodLevelAspect
{
    [OnMethodEntryAdvice]
    public void OnEntry( [Argument] CancellationToken cancellationToken )
    {
        cancellationToken.ThrowIfCancellationRequested();
    }
}

public class ReportService
{
    // The method receives the CancellationToken that the aspect checks.
    [CheckCancellation]
    public string BuildReport( string title, CancellationToken cancellationToken ) => $"Report: {title}";
}

public static class Program
{
    public static void Main()
    {
        ReportService service = new();
        Console.WriteLine( service.BuildReport( "Sales", CancellationToken.None ) );

        try
        {
            service.BuildReport( "Stock", new CancellationToken( true ) );
        }
        catch ( OperationCanceledException )
        {
            Console.WriteLine( "Stock: canceled" );
        }
    }
}
Report: Sales
Stock: canceled

See Also

Reference

ArgumentAttribute
ArgumentAmbiguityResolution
MatchPointcut

Other Resources

Advice Parameters