Skip to content

Ignore return value of MethodBase.Invoke #119933

@jl0pd

Description

@jl0pd

Description

I'm trying to write high performance RPC library that minimizes allocations. It takes interface and generate stub, which reads arguments from stream, invokes required method, then passes return value to remote caller. In order to correctly pick method I use MethodBase, since it theoretically should have minimal method lookup time. The problem I have with this API is that there's no way to tell it not to box value types. Actual return value is handled by my code and stub always return default(T) which will be ignored.

I propose that MethodBase.Invoke should support BindingFlags.IgnoreReturn. If this flag is present, then runtime should skip boxing structs and may return classes.

Reproduction Steps

Compile and execute following code:

code
using System.Reflection;

public interface IAdder
{
    int Add(int a, int b);
}

public sealed class Adder : IAdder
{
    public int Add(int a, int b) => a + b;
}

public sealed class AdderDispatcher : IAdder
{
    public int[] Args { get; set; } = new int[2];
    public IAdder Impl { get; set; } = null!;
    public Action<int> ResultHandler { get; set; } = null!;

    public int Add(int a, int b)
    {
        int result = Impl.Add(Args[0], Args[1]);
        ResultHandler.Invoke(result);
        return default;
    }
}

public static class Program
{
    public static void Main(string[] args)
    {
        var adder = new AdderDispatcher()
        {
            Args = [40, 2],
            Impl = new Adder(),
            ResultHandler = x => Console.WriteLine($"Print from callback {x}"),
        };

        var methodInfo = typeof(IAdder).GetMethod(nameof(IAdder.Add))!;
        var emptyArgs = new object?[] { null, null };

        var returnValue = methodInfo.Invoke(adder,
                                            BindingFlags.DoNotWrapExceptions | BindingFlags.IgnoreReturn,
                                            binder: null,
                                            emptyArgs,
                                            culture: null);
        Console.WriteLine($"Return value is {returnValue ?? "<null>"}");
    }
}

Expected behavior

Output is:

Print from callback 42
Return value is <null>

Actual behavior

Output is:

Print from callback 42
Return value is 0

Regression?

No, it never worked before

Known Workarounds

No response

Configuration

SDK: 9.0.305
OS: Windows 11 24h2
Arch: x64

Other information

I'm willing to implement fix for this

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions