Open sandboxFocusImprove this doc

LA0264: Several Methods Convert to the Delegate Type of an Imported Member

Severity Error
Reported by PostSharp
Message The parameter "<Parameter>" of the advice "<Advice>" is bound by [ImportMember], but several methods of the type "<TargetType>" convert to the delegate type "<DelegateType>": <Methods>. Use a delegate type whose parameter types are those of one of the methods.

Cause

An advice parameter of a delegate type, marked with ImportMemberAttribute and a method name, receives an open delegate of a method of the target type. The delegate type selects the overload, as when C# converts a method group to a delegate type: a parameter of the delegate converts to a parameter of the method by an identity or reference conversion.

When several overloads convert, PostSharp selects the one whose parameter types are the more specific, as C# overload resolution does: a type is more specific than another when it converts to it by a reference conversion, for example string than object. When no overload is more specific than all the others, PostSharp reports LA0264 on the target method. <Methods> lists the overloads that convert. This happens with parameter types that do not convert to each other, such as two interfaces that a parameter type of the delegate implements, or with an instance method and a static method that both convert.

In the following example, the delegate passes a string, which converts to both IConvertible and IEnumerable<char>, so both Write methods convert.

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

namespace Errors.LA0264_Error;

[PSerializable]
public class AnnounceAttribute : MethodLevelAspect
{
    [OnMethodEntryAdvice]
    public static void OnEntry( [This] ReportService service,
                                // A string converts to both IConvertible and IEnumerable<char>, so both Write methods convert to the delegate.
                                [ImportMember( "Write" )] Action<ReportService, string> write )
    {
        write( service, "Publishing the report." );
    }
}

public class ReportService
{
    public void Write( IConvertible value ) => Console.WriteLine( $"Value: {value}" );

    public void Write( IEnumerable<char> text ) => Console.WriteLine( $"Text: {string.Concat( text )}" );

    [Announce]
    public void Publish() => Console.WriteLine( "Report published." );
}

public static class Program
{
    public static void Main()
    {
        new ReportService().Publish();
    }
}
error LA0264: LA0264_Error.cs(28,17): The parameter "write" of the advice "Errors.LA0264_Error.AnnounceAttribute.OnEntry(Errors.LA0264_Error.ReportService, System.Action<Errors.LA0264_Error.ReportService,System.String>)" is bound by [ImportMember], but several methods of the type "Errors.LA0264_Error.ReportService" convert to the delegate type "System.Action`2<Errors.LA0264_Error.ReportService,string>": Errors.LA0264_Error.ReportService.Write(System.IConvertible), Errors.LA0264_Error.ReportService.Write(System.Collections.Generic.IEnumerable<System.Char>). Use a delegate type whose parameter types are those of one of the methods.

Resolution

Change the delegate type so that its parameter types are those of the overload you want: the other overloads then no longer convert, or the one you want is the more specific.

In the following example, the parameter of the delegate type is IEnumerable<char>, which selects Write( IEnumerable<char> ).

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

namespace Errors.LA0264_Fixed;

[PSerializable]
public class AnnounceAttribute : MethodLevelAspect
{
    [OnMethodEntryAdvice]
    public static void OnEntry( [This] ReportService service,
                                // The parameter type of the delegate is that of Write( IEnumerable<char> ), so only this method converts.
                                [ImportMember( "Write" )] Action<ReportService, IEnumerable<char>> write )
    {
        write( service, "Publishing the report." );
    }
}

public class ReportService
{
    public void Write( IConvertible value ) => Console.WriteLine( $"Value: {value}" );

    public void Write( IEnumerable<char> text ) => Console.WriteLine( $"Text: {string.Concat( text )}" );

    [Announce]
    public void Publish() => Console.WriteLine( "Report published." );
}

public static class Program
{
    public static void Main()
    {
        new ReportService().Publish();
    }
}
Text: Publishing the report.
Report published.

See Also

Reference

ImportMemberAttribute

Other Resources

Advice Parameters