Open sandboxFocusImprove this doc

LA0245: Type Parameter of a Generic Advice Cannot Be Inferred

Severity Warning
Reported by PostSharp
Message The type parameter "<TypeParameter>" of the advice "<Advice>" is not used by any parameter bound by [Argument], [Arguments], [Binding], [ImportMember], [LocationValue], [ReturnValue] or [This], so it cannot be inferred, and its type argument is object.

Cause

An advice method can be generic. For each target, PostSharp infers its type arguments from the types of the values that the parameters receive, as C# infers the type arguments of a method call. Only the parameters bound by [ArgumentAttribute], [ArgumentsAttribute], [BindingAttribute], [ImportMemberAttribute], [LocationValueAttribute], [ReturnValueAttribute] and [ThisAttribute] receive a value of the target from which a type argument can be inferred.

PostSharp reports LA0245 for each type parameter <TypeParameter> of the advice <Advice> that the types of these parameters do not use. Its type argument is then object for every target. PostSharp reports the warning once, on the advice method, and not for each target.

In the following example, the [ReturnValue] parameter is of type object, so TResult is not inferred from the return type of the method.

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

namespace Errors.LA0245_Error;

[PSerializable]
public class LogResultAttribute : MethodLevelAspect
{
    // No parameter uses TResult, so PostSharp cannot infer it, and TResult is object.
    [OnMethodSuccessAdvice]
    public static void OnSuccess<TResult>( [DeclarationName] string methodName, [ReturnValue] object? result )
    {
        Console.WriteLine( $"{methodName} returned {result} of type {typeof(TResult).Name}." );
    }
}

public class OrderService
{
    [LogResult]
    public int CountOrders() => 3;
}

public static class Program
{
    public static void Main()
    {
        new OrderService().CountOrders();
    }
}
warning LA0245: LA0245_Error.cs(13,24): The type parameter "TResult" of the advice "Errors.LA0245_Error.LogResultAttribute.OnSuccess``1(System.String, System.Object)" is not used by any parameter bound by [Argument], [Arguments], [Binding], [ImportMember], [LocationValue], [ReturnValue] or [This], so it cannot be inferred, and its type argument is object.

The program shows that TResult is object:

CountOrders returned 3 of type Object.

Resolution

  • Use the type parameter in the type of a parameter bound by one of these attributes, for instance [ReturnValue] TResult result, so that PostSharp infers it for each target.
  • Or remove the type parameter, when the advice does not need it.

In the following example, the [ReturnValue] parameter is of type TResult, which is inferred as Int32.

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

namespace Errors.LA0245_Fixed;

[PSerializable]
public class LogResultAttribute : MethodLevelAspect
{
    // The [ReturnValue] parameter is of type TResult, so PostSharp infers TResult from the return type of the method.
    [OnMethodSuccessAdvice]
    public static void OnSuccess<TResult>( [DeclarationName] string methodName, [ReturnValue] TResult result )
    {
        Console.WriteLine( $"{methodName} returned {result} of type {typeof(TResult).Name}." );
    }
}

public class OrderService
{
    [LogResult]
    public int CountOrders() => 3;
}

public static class Program
{
    public static void Main()
    {
        new OrderService().CountOrders();
    }
}
CountOrders returned 3 of type Int32.

See Also

Reference

ReturnValueAttribute
ArgumentAttribute

Other Resources

Advice Parameters