Search code examples
c#refc#-7.2

How to directly call a method with ref parameter using in parameter


I'm using a method from a legacy library: F (ref T t) where T: struct. It's declared as ref for performance reasons only and does not modify the data it receives. This library cannot be altered.

In my code I have a new method G (in T t) where T: struct that calls F.

Is there a way to call F directly with the reference I receive without copying it to a temporary first?


Solution

  • Yes, there is a way (but it uses the unsafe black magic).

    First the disclaimer.

    The fact that the method F does not modify the struct is only your "convention". For the C# compiler, a struct provided by ref is perfectly mutable.

    Having a struct provided by readonly ref via in tells the compiler: please ensure that this struct cannot be mutated.

    By the way, if you pass a struct as in, you have to ensure that this struct is declared as a readonly struct. Otherwise, the compiler will create defensive copies of the struct (read here for details.) This is the second reason why you normally cannot pass a readonly struct reference to a method accepting a struct by ref and mutating it.

    If you still want to work around all those restrictions, you can use the System.Runtime.CompilerServices.Unsafe NuGet package.

    There is a method in the Unsafe static class that can help you:

    public static ref T AsRef<T>(in T source);
    

    Here is an example:

    void F<T>(ref T t) where T : struct
    {
    }
    
    void G<T>(in T t) where T : struct
    {
        F(ref System.Runtime.CompilerServices.Unsafe.AsRef(in t));
    }